xref: /rk3399_rockchip-uboot/drivers/mtd/mtd_uboot.c (revision 504668197e7197da1a2a34a2d43ae93e5b496ded)
109c32807SHeiko Schocher /*
209c32807SHeiko Schocher  * (C) Copyright 2014
309c32807SHeiko Schocher  * Heiko Schocher, DENX Software Engineering, hs@denx.de.
409c32807SHeiko Schocher  *
509c32807SHeiko Schocher  * SPDX-License-Identifier:	GPL-2.0+
609c32807SHeiko Schocher  */
709c32807SHeiko Schocher #include <common.h>
809c32807SHeiko Schocher #include <linux/mtd/mtd.h>
9*50466819SMiquel Raynal #include <jffs2/jffs2.h> /* Legacy */
10*50466819SMiquel Raynal 
11*50466819SMiquel Raynal /**
12*50466819SMiquel Raynal  * mtd_search_alternate_name - Search an alternate name for @mtdname thanks to
13*50466819SMiquel Raynal  *                             the mtdids legacy environment variable.
14*50466819SMiquel Raynal  *
15*50466819SMiquel Raynal  * The mtdids string is a list of comma-separated 'dev_id=mtd_id' tupples.
16*50466819SMiquel Raynal  * Check if one of the mtd_id matches mtdname, in this case save dev_id in
17*50466819SMiquel Raynal  * altname.
18*50466819SMiquel Raynal  *
19*50466819SMiquel Raynal  * @mtdname: Current MTD device name
20*50466819SMiquel Raynal  * @altname: Alternate name to return
21*50466819SMiquel Raynal  * @max_len: Length of the alternate name buffer
22*50466819SMiquel Raynal  *
23*50466819SMiquel Raynal  * @return 0 on success, an error otherwise.
24*50466819SMiquel Raynal  */
25*50466819SMiquel Raynal int mtd_search_alternate_name(const char *mtdname, char *altname,
26*50466819SMiquel Raynal 			      unsigned int max_len)
27*50466819SMiquel Raynal {
28*50466819SMiquel Raynal 	const char *mtdids, *equal, *comma, *dev_id, *mtd_id;
29*50466819SMiquel Raynal 	int dev_id_len, mtd_id_len;
30*50466819SMiquel Raynal 
31*50466819SMiquel Raynal 	mtdids = env_get("mtdids");
32*50466819SMiquel Raynal 	if (!mtdids)
33*50466819SMiquel Raynal 		return -EINVAL;
34*50466819SMiquel Raynal 
35*50466819SMiquel Raynal 	do {
36*50466819SMiquel Raynal 		/* Find the '=' sign */
37*50466819SMiquel Raynal 		dev_id = mtdids;
38*50466819SMiquel Raynal 		equal = strchr(dev_id, '=');
39*50466819SMiquel Raynal 		if (!equal)
40*50466819SMiquel Raynal 			break;
41*50466819SMiquel Raynal 		dev_id_len = equal - mtdids;
42*50466819SMiquel Raynal 		mtd_id = equal + 1;
43*50466819SMiquel Raynal 
44*50466819SMiquel Raynal 		/* Find the end of the tupple */
45*50466819SMiquel Raynal 		comma = strchr(mtdids, ',');
46*50466819SMiquel Raynal 		if (comma)
47*50466819SMiquel Raynal 			mtd_id_len = comma - mtd_id;
48*50466819SMiquel Raynal 		else
49*50466819SMiquel Raynal 			mtd_id_len = &mtdids[strlen(mtdids)] - mtd_id + 1;
50*50466819SMiquel Raynal 
51*50466819SMiquel Raynal 		if (!dev_id_len || !mtd_id_len)
52*50466819SMiquel Raynal 			return -EINVAL;
53*50466819SMiquel Raynal 
54*50466819SMiquel Raynal 		if (dev_id_len + 1 > max_len)
55*50466819SMiquel Raynal 			continue;
56*50466819SMiquel Raynal 
57*50466819SMiquel Raynal 		/* Compare the name we search with the current mtd_id */
58*50466819SMiquel Raynal 		if (!strncmp(mtdname, mtd_id, mtd_id_len)) {
59*50466819SMiquel Raynal 			strncpy(altname, dev_id, dev_id_len);
60*50466819SMiquel Raynal 			altname[dev_id_len] = 0;
61*50466819SMiquel Raynal 
62*50466819SMiquel Raynal 			return 0;
63*50466819SMiquel Raynal 		}
64*50466819SMiquel Raynal 
65*50466819SMiquel Raynal 		/* Go to the next tupple */
66*50466819SMiquel Raynal 		mtdids = comma + 1;
67*50466819SMiquel Raynal 	} while (comma);
68*50466819SMiquel Raynal 
69*50466819SMiquel Raynal 	return -EINVAL;
70*50466819SMiquel Raynal }
71*50466819SMiquel Raynal 
72*50466819SMiquel Raynal /* Legacy */
7309c32807SHeiko Schocher 
7409c32807SHeiko Schocher static int get_part(const char *partname, int *idx, loff_t *off, loff_t *size,
7509c32807SHeiko Schocher 		loff_t *maxsize, int devtype)
7609c32807SHeiko Schocher {
7709c32807SHeiko Schocher #ifdef CONFIG_CMD_MTDPARTS
7809c32807SHeiko Schocher 	struct mtd_device *dev;
7909c32807SHeiko Schocher 	struct part_info *part;
8009c32807SHeiko Schocher 	u8 pnum;
8109c32807SHeiko Schocher 	int ret;
8209c32807SHeiko Schocher 
8309c32807SHeiko Schocher 	ret = mtdparts_init();
8409c32807SHeiko Schocher 	if (ret)
8509c32807SHeiko Schocher 		return ret;
8609c32807SHeiko Schocher 
8709c32807SHeiko Schocher 	ret = find_dev_and_part(partname, &dev, &pnum, &part);
8809c32807SHeiko Schocher 	if (ret)
8909c32807SHeiko Schocher 		return ret;
9009c32807SHeiko Schocher 
9109c32807SHeiko Schocher 	if (dev->id->type != devtype) {
9209c32807SHeiko Schocher 		printf("not same typ %d != %d\n", dev->id->type, devtype);
9309c32807SHeiko Schocher 		return -1;
9409c32807SHeiko Schocher 	}
9509c32807SHeiko Schocher 
9609c32807SHeiko Schocher 	*off = part->offset;
9709c32807SHeiko Schocher 	*size = part->size;
9809c32807SHeiko Schocher 	*maxsize = part->size;
9909c32807SHeiko Schocher 	*idx = dev->id->num;
10009c32807SHeiko Schocher 
10109c32807SHeiko Schocher 	return 0;
10209c32807SHeiko Schocher #else
10310b69712SMaxime Ripard 	puts("mtdparts support missing.\n");
10409c32807SHeiko Schocher 	return -1;
10509c32807SHeiko Schocher #endif
10609c32807SHeiko Schocher }
10709c32807SHeiko Schocher 
10809c32807SHeiko Schocher int mtd_arg_off(const char *arg, int *idx, loff_t *off, loff_t *size,
109f18d1116SMasahiro Yamada 		loff_t *maxsize, int devtype, uint64_t chipsize)
11009c32807SHeiko Schocher {
11109c32807SHeiko Schocher 	if (!str2off(arg, off))
11209c32807SHeiko Schocher 		return get_part(arg, idx, off, size, maxsize, devtype);
11309c32807SHeiko Schocher 
11409c32807SHeiko Schocher 	if (*off >= chipsize) {
11509c32807SHeiko Schocher 		puts("Offset exceeds device limit\n");
11609c32807SHeiko Schocher 		return -1;
11709c32807SHeiko Schocher 	}
11809c32807SHeiko Schocher 
11909c32807SHeiko Schocher 	*maxsize = chipsize - *off;
12009c32807SHeiko Schocher 	*size = *maxsize;
12109c32807SHeiko Schocher 	return 0;
12209c32807SHeiko Schocher }
12309c32807SHeiko Schocher 
12409c32807SHeiko Schocher int mtd_arg_off_size(int argc, char *const argv[], int *idx, loff_t *off,
125f18d1116SMasahiro Yamada 		     loff_t *size, loff_t *maxsize, int devtype,
126f18d1116SMasahiro Yamada 		     uint64_t chipsize)
12709c32807SHeiko Schocher {
12809c32807SHeiko Schocher 	int ret;
12909c32807SHeiko Schocher 
13009c32807SHeiko Schocher 	if (argc == 0) {
13109c32807SHeiko Schocher 		*off = 0;
13209c32807SHeiko Schocher 		*size = chipsize;
13309c32807SHeiko Schocher 		*maxsize = *size;
13409c32807SHeiko Schocher 		goto print;
13509c32807SHeiko Schocher 	}
13609c32807SHeiko Schocher 
13709c32807SHeiko Schocher 	ret = mtd_arg_off(argv[0], idx, off, size, maxsize, devtype,
13809c32807SHeiko Schocher 			  chipsize);
13909c32807SHeiko Schocher 	if (ret)
14009c32807SHeiko Schocher 		return ret;
14109c32807SHeiko Schocher 
14209c32807SHeiko Schocher 	if (argc == 1)
14309c32807SHeiko Schocher 		goto print;
14409c32807SHeiko Schocher 
14509c32807SHeiko Schocher 	if (!str2off(argv[1], size)) {
14609c32807SHeiko Schocher 		printf("'%s' is not a number\n", argv[1]);
14709c32807SHeiko Schocher 		return -1;
14809c32807SHeiko Schocher 	}
14909c32807SHeiko Schocher 
15009c32807SHeiko Schocher 	if (*size > *maxsize) {
15109c32807SHeiko Schocher 		puts("Size exceeds partition or device limit\n");
15209c32807SHeiko Schocher 		return -1;
15309c32807SHeiko Schocher 	}
15409c32807SHeiko Schocher 
15509c32807SHeiko Schocher print:
15609c32807SHeiko Schocher 	printf("device %d ", *idx);
15709c32807SHeiko Schocher 	if (*size == chipsize)
15809c32807SHeiko Schocher 		puts("whole chip\n");
15909c32807SHeiko Schocher 	else
16009c32807SHeiko Schocher 		printf("offset 0x%llx, size 0x%llx\n",
16109c32807SHeiko Schocher 		       (unsigned long long)*off, (unsigned long long)*size);
16209c32807SHeiko Schocher 	return 0;
16309c32807SHeiko Schocher }
164