]>
git.ipfire.org Git - thirdparty/u-boot.git/blob - drivers/mtd/mtd_uboot.c
1 // SPDX-License-Identifier: GPL-2.0+
4 * Heiko Schocher, DENX Software Engineering, hs@denx.de.
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>
19 #define MTD_NAME_MAX_LEN 20
21 void board_mtdparts_default(const char **mtdids
, const char **mtdparts
);
23 static const char *get_mtdids(void)
25 __maybe_unused
const char *mtdparts
= NULL
;
26 const char *mtdids
= env_get("mtdids");
31 #if defined(CONFIG_SYS_MTDPARTS_RUNTIME)
32 board_mtdparts_default(&mtdids
, &mtdparts
);
33 #elif defined(CONFIG_MTDIDS_DEFAULT)
34 mtdids
= CONFIG_MTDIDS_DEFAULT
;
38 env_set("mtdids", mtdids
);
44 * mtd_search_alternate_name - Search an alternate name for @mtdname thanks to
45 * the mtdids legacy environment variable.
47 * The mtdids string is a list of comma-separated 'dev_id=mtd_id' tupples.
48 * Check if one of the mtd_id matches mtdname, in this case save dev_id in
51 * @mtdname: Current MTD device name
52 * @altname: Alternate name to return
53 * @max_len: Length of the alternate name buffer
55 * Return: 0 on success, an error otherwise.
57 int mtd_search_alternate_name(const char *mtdname
, char *altname
,
60 const char *mtdids
, *equal
, *comma
, *dev_id
, *mtd_id
;
61 int dev_id_len
, mtd_id_len
;
63 mtdids
= get_mtdids();
68 /* Find the '=' sign */
70 equal
= strchr(dev_id
, '=');
73 dev_id_len
= equal
- mtdids
;
76 /* Find the end of the tupple */
77 comma
= strchr(mtdids
, ',');
79 mtd_id_len
= comma
- mtd_id
;
81 mtd_id_len
= &mtdids
[strlen(mtdids
)] - mtd_id
+ 1;
83 if (!dev_id_len
|| !mtd_id_len
)
86 if (dev_id_len
+ 1 > max_len
)
89 /* Compare the name we search with the current mtd_id */
90 if (!strncmp(mtdname
, mtd_id
, mtd_id_len
)) {
91 strncpy(altname
, dev_id
, dev_id_len
);
92 altname
[dev_id_len
] = 0;
97 /* Go to the next tupple */
104 #if IS_ENABLED(CONFIG_DM_MTD)
105 static void mtd_probe_uclass_mtd_devs(void)
109 uclass_foreach_dev_probe(UCLASS_MTD
, dev
)
113 static void mtd_probe_uclass_mtd_devs(void) { }
116 #if IS_ENABLED(CONFIG_DM_SPI_FLASH) && IS_ENABLED(CONFIG_SPI_FLASH_MTD)
117 static void mtd_probe_uclass_spi_nor_devs(void)
121 uclass_foreach_dev_probe(UCLASS_SPI_FLASH
, dev
)
125 static void mtd_probe_uclass_spi_nor_devs(void) { }
128 #if defined(CONFIG_MTD_PARTITIONS)
130 #define MTDPARTS_MAXLEN 512
132 static const char *get_mtdparts(void)
134 __maybe_unused
const char *mtdids
= NULL
;
135 static char tmp_parts
[MTDPARTS_MAXLEN
];
136 const char *mtdparts
= NULL
;
138 if (gd
->flags
& GD_FLG_ENV_READY
)
139 mtdparts
= env_get("mtdparts");
140 else if (env_get_f("mtdparts", tmp_parts
, sizeof(tmp_parts
)) != -1)
141 mtdparts
= tmp_parts
;
146 #if defined(CONFIG_SYS_MTDPARTS_RUNTIME)
147 board_mtdparts_default(&mtdids
, &mtdparts
);
148 #elif defined(CONFIG_MTDPARTS_DEFAULT)
149 mtdparts
= CONFIG_MTDPARTS_DEFAULT
;
153 env_set("mtdparts", mtdparts
);
158 static int mtd_del_parts(struct mtd_info
*mtd
, bool quiet
)
162 if (!mtd_has_partitions(mtd
))
165 /* do not delete partitions if they are in use. */
166 if (mtd_partitions_used(mtd
)) {
168 printf("\"%s\" partitions still in use, can't delete them\n",
173 ret
= del_mtd_partitions(mtd
);
180 static bool mtd_del_all_parts_failed
;
182 static void mtd_del_all_parts(void)
184 struct mtd_info
*mtd
;
187 mtd_del_all_parts_failed
= false;
190 * It is not safe to remove entries from the mtd_for_each_device loop
191 * as it uses idr indexes and the partitions removal is done in bulk
192 * (all partitions of one device at the same time), so break and
193 * iterate from start each time a new partition is found and deleted.
196 mtd_for_each_device(mtd
) {
197 ret
= mtd_del_parts(mtd
, false);
201 mtd_del_all_parts_failed
= true;
206 static int parse_mtdparts(const char *mtdparts
, const char *mtdids
)
208 const char *mtdparts_next
;
209 struct mtd_info
*mtd
;
211 /* Start the parsing by ignoring the extra 'mtdparts=' prefix, if any */
212 if (!strncmp(mtdparts
, "mtdparts=", sizeof("mtdparts=") - 1))
215 /* For each MTD device in mtdparts */
216 for (; mtdparts
[0] != '\0'; mtdparts
= mtdparts_next
) {
217 char mtd_name
[MTD_NAME_MAX_LEN
], *colon
;
218 struct mtd_partition
*parts
;
219 unsigned int mtd_name_len
;
222 mtdparts_next
= strchr(mtdparts
, ';');
224 mtdparts_next
= mtdparts
+ strlen(mtdparts
);
228 colon
= strchr(mtdparts
, ':');
229 if (colon
> mtdparts_next
)
233 printf("Wrong mtdparts: %s\n", mtdparts
);
237 mtd_name_len
= (unsigned int)(colon
- mtdparts
);
238 if (mtd_name_len
+ 1 > sizeof(mtd_name
)) {
239 printf("MTD name too long: %s\n", mtdparts
);
243 strncpy(mtd_name
, mtdparts
, mtd_name_len
);
244 mtd_name
[mtd_name_len
] = '\0';
245 /* Move the pointer forward (including the ':') */
246 mtdparts
+= mtd_name_len
+ 1;
247 mtd
= get_mtd_device_nm(mtd_name
);
248 if (IS_ERR_OR_NULL(mtd
)) {
249 char linux_name
[MTD_NAME_MAX_LEN
];
252 * The MTD device named "mtd_name" does not exist. Try
253 * to find a correspondance with an MTD device having
254 * the same type and number as defined in the mtdids.
256 debug("No device named %s\n", mtd_name
);
257 ret
= mtd_search_alternate_name(mtd_name
, linux_name
,
260 mtd
= get_mtd_device_nm(linux_name
);
263 * If no device could be found, move the mtdparts
264 * pointer forward until the next set of partitions.
266 if (ret
|| IS_ERR_OR_NULL(mtd
)) {
267 printf("Could not find a valid device for %s\n",
269 mtdparts
= mtdparts_next
;
275 * Call mtd_del_parts() again, even if it's already been called
276 * in mtd_del_all_parts(). We need to know if old partitions are
277 * still around (because they are still being used by someone),
278 * and if they are, we shouldn't create new partitions, so just
279 * skip this MTD device and try the next one.
281 ret
= mtd_del_parts(mtd
, true);
286 * Parse the MTD device partitions. It will update the mtdparts
287 * pointer, create an array of parts (that must be freed), and
288 * return the number of partition structures in the array.
290 ret
= mtd_parse_partitions(mtd
, &mtdparts
, &parts
, &nparts
);
292 printf("Could not parse device %s\n", mtd
->name
);
300 /* Create the new MTD partitions */
301 add_mtd_partitions(mtd
, parts
, nparts
);
303 /* Free the structures allocated during the parsing */
304 mtd_free_parsed_partitions(parts
, nparts
);
312 int mtd_probe_devices(void)
314 static char *old_mtdparts
;
315 static char *old_mtdids
;
316 const char *mtdparts
= get_mtdparts();
317 const char *mtdids
= get_mtdids();
318 struct mtd_info
*mtd
;
320 mtd_probe_uclass_mtd_devs();
321 mtd_probe_uclass_spi_nor_devs();
324 * Check if mtdparts/mtdids changed, if the MTD dev list was updated
325 * or if our previous attempt to delete existing partititions failed.
326 * In any of these cases we want to update the partitions, otherwise,
327 * everything is up-to-date and we can return 0 directly.
329 if ((!mtdparts
&& !old_mtdparts
&& !mtdids
&& !old_mtdids
) ||
330 (mtdparts
&& old_mtdparts
&& mtdids
&& old_mtdids
&&
331 !mtd_dev_list_updated() && !mtd_del_all_parts_failed
&&
332 !strcmp(mtdparts
, old_mtdparts
) &&
333 !strcmp(mtdids
, old_mtdids
)))
336 /* Update the local copy of mtdparts */
339 old_mtdparts
= strdup(mtdparts
);
340 old_mtdids
= strdup(mtdids
);
343 * Remove all old parts. Note that partition removal can fail in case
344 * one of the partition is still being used by an MTD user, so this
345 * does not guarantee that all old partitions are gone.
350 * Call mtd_dev_list_updated() to clear updates generated by our own
351 * parts removal loop.
353 mtd_dev_list_updated();
355 /* If both mtdparts and mtdids are non-empty, parse */
356 if (mtdparts
&& mtdids
) {
357 if (parse_mtdparts(mtdparts
, mtdids
) < 0)
358 printf("Failed parsing MTD partitions from mtdparts!\n");
361 /* Fallback to OF partitions */
362 mtd_for_each_device(mtd
) {
363 if (list_empty(&mtd
->partitions
)) {
364 if (add_mtd_partitions_of(mtd
) < 0)
365 printf("Failed parsing MTD %s OF partitions!\n",
371 * Call mtd_dev_list_updated() to clear updates generated by our own
372 * parts registration loop.
374 mtd_dev_list_updated();
379 int mtd_probe_devices(void)
381 mtd_probe_uclass_mtd_devs();
382 mtd_probe_uclass_spi_nor_devs();
386 #endif /* defined(CONFIG_MTD_PARTITIONS) */