1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2014
4  * Heiko Schocher, DENX Software Engineering, hs@denx.de.
5  */
6 #include <common.h>
7 #include <env.h>
8 #include <log.h>
9 #include <malloc.h>
10 #include <dm/device.h>
11 #include <dm/uclass-internal.h>
12 #include <dm/uclass.h>
13 #include <linux/err.h>
14 #include <linux/mtd/mtd.h>
15 #include <linux/mtd/partitions.h>
16 #include <asm/global_data.h>
17 #include <mtd.h>
18 
19 #define MTD_NAME_MAX_LEN 20
20 
21 void board_mtdparts_default(const char **mtdids, const char **mtdparts);
22 
get_mtdids(void)23 static const char *get_mtdids(void)
24 {
25 	__maybe_unused const char *mtdparts = NULL;
26 	const char *mtdids = env_get("mtdids");
27 
28 	if (mtdids)
29 		return mtdids;
30 
31 #if defined(CONFIG_SYS_MTDPARTS_RUNTIME)
32 	board_mtdparts_default(&mtdids, &mtdparts);
33 #elif defined(MTDIDS_DEFAULT)
34 	mtdids = MTDIDS_DEFAULT;
35 #elif defined(CONFIG_MTDIDS_DEFAULT)
36 	mtdids = CONFIG_MTDIDS_DEFAULT;
37 #endif
38 
39 	if (mtdids)
40 		env_set("mtdids", mtdids);
41 
42 	return mtdids;
43 }
44 
45 /**
46  * mtd_search_alternate_name - Search an alternate name for @mtdname thanks to
47  *                             the mtdids legacy environment variable.
48  *
49  * The mtdids string is a list of comma-separated 'dev_id=mtd_id' tupples.
50  * Check if one of the mtd_id matches mtdname, in this case save dev_id in
51  * altname.
52  *
53  * @mtdname: Current MTD device name
54  * @altname: Alternate name to return
55  * @max_len: Length of the alternate name buffer
56  *
57  * @return 0 on success, an error otherwise.
58  */
mtd_search_alternate_name(const char * mtdname,char * altname,unsigned int max_len)59 int mtd_search_alternate_name(const char *mtdname, char *altname,
60 			      unsigned int max_len)
61 {
62 	const char *mtdids, *equal, *comma, *dev_id, *mtd_id;
63 	int dev_id_len, mtd_id_len;
64 
65 	mtdids = get_mtdids();
66 	if (!mtdids)
67 		return -EINVAL;
68 
69 	do {
70 		/* Find the '=' sign */
71 		dev_id = mtdids;
72 		equal = strchr(dev_id, '=');
73 		if (!equal)
74 			break;
75 		dev_id_len = equal - mtdids;
76 		mtd_id = equal + 1;
77 
78 		/* Find the end of the tupple */
79 		comma = strchr(mtdids, ',');
80 		if (comma)
81 			mtd_id_len = comma - mtd_id;
82 		else
83 			mtd_id_len = &mtdids[strlen(mtdids)] - mtd_id + 1;
84 
85 		if (!dev_id_len || !mtd_id_len)
86 			return -EINVAL;
87 
88 		if (dev_id_len + 1 > max_len)
89 			continue;
90 
91 		/* Compare the name we search with the current mtd_id */
92 		if (!strncmp(mtdname, mtd_id, mtd_id_len)) {
93 			strncpy(altname, dev_id, dev_id_len);
94 			altname[dev_id_len] = 0;
95 
96 			return 0;
97 		}
98 
99 		/* Go to the next tupple */
100 		mtdids = comma + 1;
101 	} while (comma);
102 
103 	return -EINVAL;
104 }
105 
106 #if IS_ENABLED(CONFIG_DM_MTD)
mtd_probe_uclass_mtd_devs(void)107 static void mtd_probe_uclass_mtd_devs(void)
108 {
109 	struct udevice *dev;
110 
111 	uclass_foreach_dev_probe(UCLASS_MTD, dev)
112 		;
113 }
114 #else
mtd_probe_uclass_mtd_devs(void)115 static void mtd_probe_uclass_mtd_devs(void) { }
116 #endif
117 
118 #if IS_ENABLED(CONFIG_DM_SPI_FLASH) && IS_ENABLED(CONFIG_SPI_FLASH_MTD)
mtd_probe_uclass_spi_nor_devs(void)119 static void mtd_probe_uclass_spi_nor_devs(void)
120 {
121 	struct udevice *dev;
122 
123 	uclass_foreach_dev_probe(UCLASS_SPI_FLASH, dev)
124 		;
125 }
126 #else
mtd_probe_uclass_spi_nor_devs(void)127 static void mtd_probe_uclass_spi_nor_devs(void) { }
128 #endif
129 
130 #if defined(CONFIG_MTD_PARTITIONS)
131 
132 #define MTDPARTS_MAXLEN         512
133 
get_mtdparts(void)134 static const char *get_mtdparts(void)
135 {
136 	__maybe_unused const char *mtdids = NULL;
137 	static char tmp_parts[MTDPARTS_MAXLEN];
138 	const char *mtdparts = NULL;
139 
140 	if (gd->flags & GD_FLG_ENV_READY)
141 		mtdparts = env_get("mtdparts");
142 	else if (env_get_f("mtdparts", tmp_parts, sizeof(tmp_parts)) != -1)
143 		mtdparts = tmp_parts;
144 
145 	if (mtdparts)
146 		return mtdparts;
147 
148 #if defined(CONFIG_SYS_MTDPARTS_RUNTIME)
149 	board_mtdparts_default(&mtdids, &mtdparts);
150 #elif defined(MTDPARTS_DEFAULT)
151 	mtdparts = MTDPARTS_DEFAULT;
152 #elif defined(CONFIG_MTDPARTS_DEFAULT)
153 	mtdparts = CONFIG_MTDPARTS_DEFAULT;
154 #endif
155 
156 	if (mtdparts)
157 		env_set("mtdparts", mtdparts);
158 
159 	return mtdparts;
160 }
161 
mtd_del_parts(struct mtd_info * mtd,bool quiet)162 static int mtd_del_parts(struct mtd_info *mtd, bool quiet)
163 {
164 	int ret;
165 
166 	if (!mtd_has_partitions(mtd))
167 		return 0;
168 
169 	/* do not delete partitions if they are in use. */
170 	if (mtd_partitions_used(mtd)) {
171 		if (!quiet)
172 			printf("\"%s\" partitions still in use, can't delete them\n",
173 			       mtd->name);
174 		return -EACCES;
175 	}
176 
177 	ret = del_mtd_partitions(mtd);
178 	if (ret)
179 		return ret;
180 
181 	return 1;
182 }
183 
184 static bool mtd_del_all_parts_failed;
185 
mtd_del_all_parts(void)186 static void mtd_del_all_parts(void)
187 {
188 	struct mtd_info *mtd;
189 	int ret = 0;
190 
191 	mtd_del_all_parts_failed = false;
192 
193 	/*
194 	 * It is not safe to remove entries from the mtd_for_each_device loop
195 	 * as it uses idr indexes and the partitions removal is done in bulk
196 	 * (all partitions of one device at the same time), so break and
197 	 * iterate from start each time a new partition is found and deleted.
198 	 */
199 	do {
200 		mtd_for_each_device(mtd) {
201 			ret = mtd_del_parts(mtd, false);
202 			if (ret > 0)
203 				break;
204 			else if (ret < 0)
205 				mtd_del_all_parts_failed = true;
206 		}
207 	} while (ret > 0);
208 }
209 
parse_mtdparts(const char * mtdparts,const char * mtdids)210 static int parse_mtdparts(const char *mtdparts, const char *mtdids)
211 {
212 	const char *mtdparts_next;
213 	struct mtd_info *mtd;
214 
215 	/* Start the parsing by ignoring the extra 'mtdparts=' prefix, if any */
216 	if (!strncmp(mtdparts, "mtdparts=", sizeof("mtdparts=") - 1))
217 		mtdparts += 9;
218 
219 	/* For each MTD device in mtdparts */
220 	for (; mtdparts[0] != '\0'; mtdparts = mtdparts_next) {
221 		char mtd_name[MTD_NAME_MAX_LEN], *colon;
222 		struct mtd_partition *parts;
223 		unsigned int mtd_name_len;
224 		int nparts, ret;
225 
226 		mtdparts_next = strchr(mtdparts, ';');
227 		if (!mtdparts_next)
228 			mtdparts_next = mtdparts + strlen(mtdparts);
229 		else
230 			mtdparts_next++;
231 
232 		colon = strchr(mtdparts, ':');
233 		if (colon > mtdparts_next)
234 			colon = NULL;
235 
236 		if (!colon) {
237 			printf("Wrong mtdparts: %s\n", mtdparts);
238 			return -EINVAL;
239 		}
240 
241 		mtd_name_len = (unsigned int)(colon - mtdparts);
242 		if (mtd_name_len + 1 > sizeof(mtd_name)) {
243 			printf("MTD name too long: %s\n", mtdparts);
244 			return -EINVAL;
245 		}
246 
247 		strncpy(mtd_name, mtdparts, mtd_name_len);
248 		mtd_name[mtd_name_len] = '\0';
249 		/* Move the pointer forward (including the ':') */
250 		mtdparts += mtd_name_len + 1;
251 		mtd = get_mtd_device_nm(mtd_name);
252 		if (IS_ERR_OR_NULL(mtd)) {
253 			char linux_name[MTD_NAME_MAX_LEN];
254 
255 			/*
256 			 * The MTD device named "mtd_name" does not exist. Try
257 			 * to find a correspondance with an MTD device having
258 			 * the same type and number as defined in the mtdids.
259 			 */
260 			debug("No device named %s\n", mtd_name);
261 			ret = mtd_search_alternate_name(mtd_name, linux_name,
262 							MTD_NAME_MAX_LEN);
263 			if (!ret)
264 				mtd = get_mtd_device_nm(linux_name);
265 
266 			/*
267 			 * If no device could be found, move the mtdparts
268 			 * pointer forward until the next set of partitions.
269 			 */
270 			if (ret || IS_ERR_OR_NULL(mtd)) {
271 				printf("Could not find a valid device for %s\n",
272 				       mtd_name);
273 				mtdparts = mtdparts_next;
274 				continue;
275 			}
276 		}
277 
278 		/*
279 		 * Call mtd_del_parts() again, even if it's already been called
280 		 * in mtd_del_all_parts(). We need to know if old partitions are
281 		 * still around (because they are still being used by someone),
282 		 * and if they are, we shouldn't create new partitions, so just
283 		 * skip this MTD device and try the next one.
284 		 */
285 		ret = mtd_del_parts(mtd, true);
286 		if (ret < 0)
287 			continue;
288 
289 		/*
290 		 * Parse the MTD device partitions. It will update the mtdparts
291 		 * pointer, create an array of parts (that must be freed), and
292 		 * return the number of partition structures in the array.
293 		 */
294 		ret = mtd_parse_partitions(mtd, &mtdparts, &parts, &nparts);
295 		if (ret) {
296 			printf("Could not parse device %s\n", mtd->name);
297 			put_mtd_device(mtd);
298 			return -EINVAL;
299 		}
300 
301 		if (!nparts)
302 			continue;
303 
304 		/* Create the new MTD partitions */
305 		add_mtd_partitions(mtd, parts, nparts);
306 
307 		/* Free the structures allocated during the parsing */
308 		mtd_free_parsed_partitions(parts, nparts);
309 
310 		put_mtd_device(mtd);
311 	}
312 
313 	return 0;
314 }
315 
mtd_probe_devices(void)316 int mtd_probe_devices(void)
317 {
318 	static char *old_mtdparts;
319 	static char *old_mtdids;
320 	const char *mtdparts = get_mtdparts();
321 	const char *mtdids = get_mtdids();
322 	struct mtd_info *mtd;
323 
324 	mtd_probe_uclass_mtd_devs();
325 	mtd_probe_uclass_spi_nor_devs();
326 
327 	/*
328 	 * Check if mtdparts/mtdids changed, if the MTD dev list was updated
329 	 * or if our previous attempt to delete existing partititions failed.
330 	 * In any of these cases we want to update the partitions, otherwise,
331 	 * everything is up-to-date and we can return 0 directly.
332 	 */
333 	if ((!mtdparts && !old_mtdparts && !mtdids && !old_mtdids) ||
334 	    (mtdparts && old_mtdparts && mtdids && old_mtdids &&
335 	     !mtd_dev_list_updated() && !mtd_del_all_parts_failed &&
336 	     !strcmp(mtdparts, old_mtdparts) &&
337 	     !strcmp(mtdids, old_mtdids)))
338 		return 0;
339 
340 	/* Update the local copy of mtdparts */
341 	free(old_mtdparts);
342 	free(old_mtdids);
343 	old_mtdparts = strdup(mtdparts);
344 	old_mtdids = strdup(mtdids);
345 
346 	/*
347 	 * Remove all old parts. Note that partition removal can fail in case
348 	 * one of the partition is still being used by an MTD user, so this
349 	 * does not guarantee that all old partitions are gone.
350 	 */
351 	mtd_del_all_parts();
352 
353 	/*
354 	 * Call mtd_dev_list_updated() to clear updates generated by our own
355 	 * parts removal loop.
356 	 */
357 	mtd_dev_list_updated();
358 
359 	/* If both mtdparts and mtdids are non-empty, parse */
360 	if (mtdparts && mtdids) {
361 		if (parse_mtdparts(mtdparts, mtdids) < 0)
362 			printf("Failed parsing MTD partitions from mtdparts!\n");
363 	}
364 
365 	/* Fallback to OF partitions */
366 	mtd_for_each_device(mtd) {
367 		if (list_empty(&mtd->partitions)) {
368 			if (add_mtd_partitions_of(mtd) < 0)
369 				printf("Failed parsing MTD %s OF partitions!\n",
370 					mtd->name);
371 		}
372 	}
373 
374 	/*
375 	 * Call mtd_dev_list_updated() to clear updates generated by our own
376 	 * parts registration loop.
377 	 */
378 	mtd_dev_list_updated();
379 
380 	return 0;
381 }
382 #else
mtd_probe_devices(void)383 int mtd_probe_devices(void)
384 {
385 	mtd_probe_uclass_mtd_devs();
386 	mtd_probe_uclass_spi_nor_devs();
387 
388 	return 0;
389 }
390 #endif /* defined(CONFIG_MTD_PARTITIONS) */
391