xref: /rk3399_rockchip-uboot/drivers/mtd/mtd_uboot.c (revision fe85de89e43efd43a175b1ece864ce20f4f1244d)
1 /*
2  * (C) Copyright 2014
3  * Heiko Schocher, DENX Software Engineering, hs@denx.de.
4  *
5  * SPDX-License-Identifier:	GPL-2.0+
6  */
7 #include <common.h>
8 #include <linux/mtd/mtd.h>
9 #include <jffs2/jffs2.h> /* Legacy */
10 
11 /**
12  * mtd_search_alternate_name - Search an alternate name for @mtdname thanks to
13  *                             the mtdids legacy environment variable.
14  *
15  * The mtdids string is a list of comma-separated 'dev_id=mtd_id' tupples.
16  * Check if one of the mtd_id matches mtdname, in this case save dev_id in
17  * altname.
18  *
19  * @mtdname: Current MTD device name
20  * @altname: Alternate name to return
21  * @max_len: Length of the alternate name buffer
22  *
23  * @return 0 on success, an error otherwise.
24  */
25 int mtd_search_alternate_name(const char *mtdname, char *altname,
26 			      unsigned int max_len)
27 {
28 	const char *mtdids, *equal, *comma, *dev_id, *mtd_id;
29 	int dev_id_len, mtd_id_len;
30 
31 	mtdids = env_get("mtdids");
32 	if (!mtdids)
33 		return -EINVAL;
34 
35 	do {
36 		/* Find the '=' sign */
37 		dev_id = mtdids;
38 		equal = strchr(dev_id, '=');
39 		if (!equal)
40 			break;
41 		dev_id_len = equal - mtdids;
42 		mtd_id = equal + 1;
43 
44 		/* Find the end of the tupple */
45 		comma = strchr(mtdids, ',');
46 		if (comma)
47 			mtd_id_len = comma - mtd_id;
48 		else
49 			mtd_id_len = &mtdids[strlen(mtdids)] - mtd_id + 1;
50 
51 		if (!dev_id_len || !mtd_id_len)
52 			return -EINVAL;
53 
54 		if (dev_id_len + 1 > max_len)
55 			continue;
56 
57 		/* Compare the name we search with the current mtd_id */
58 		if (!strncmp(mtdname, mtd_id, mtd_id_len)) {
59 			strncpy(altname, dev_id, dev_id_len);
60 			altname[dev_id_len] = 0;
61 
62 			return 0;
63 		}
64 
65 		/* Go to the next tupple */
66 		mtdids = comma + 1;
67 	} while (comma);
68 
69 	return -EINVAL;
70 }
71 
72 /* Legacy */
73 
74 static int get_part(const char *partname, int *idx, loff_t *off, loff_t *size,
75 		loff_t *maxsize, int devtype)
76 {
77 #ifdef CONFIG_CMD_MTDPARTS
78 	struct mtd_device *dev;
79 	struct part_info *part;
80 	u8 pnum;
81 	int ret;
82 
83 	ret = mtdparts_init();
84 	if (ret)
85 		return ret;
86 
87 	ret = find_dev_and_part(partname, &dev, &pnum, &part);
88 	if (ret)
89 		return ret;
90 
91 	if (dev->id->type != devtype) {
92 		printf("not same typ %d != %d\n", dev->id->type, devtype);
93 		return -1;
94 	}
95 
96 	*off = part->offset;
97 	*size = part->size;
98 	*maxsize = part->size;
99 	*idx = dev->id->num;
100 
101 	return 0;
102 #else
103 	puts("mtdparts support missing.\n");
104 	return -1;
105 #endif
106 }
107 
108 int mtd_arg_off(const char *arg, int *idx, loff_t *off, loff_t *size,
109 		loff_t *maxsize, int devtype, uint64_t chipsize)
110 {
111 	if (!str2off(arg, off))
112 		return get_part(arg, idx, off, size, maxsize, devtype);
113 
114 	if (*off >= chipsize) {
115 		puts("Offset exceeds device limit\n");
116 		return -1;
117 	}
118 
119 	*maxsize = chipsize - *off;
120 	*size = *maxsize;
121 	return 0;
122 }
123 
124 int mtd_arg_off_size(int argc, char *const argv[], int *idx, loff_t *off,
125 		     loff_t *size, loff_t *maxsize, int devtype,
126 		     uint64_t chipsize)
127 {
128 	int ret;
129 
130 	if (argc == 0) {
131 		*off = 0;
132 		*size = chipsize;
133 		*maxsize = *size;
134 		goto print;
135 	}
136 
137 	ret = mtd_arg_off(argv[0], idx, off, size, maxsize, devtype,
138 			  chipsize);
139 	if (ret)
140 		return ret;
141 
142 	if (argc == 1)
143 		goto print;
144 
145 	if (!str2off(argv[1], size)) {
146 		printf("'%s' is not a number\n", argv[1]);
147 		return -1;
148 	}
149 
150 	if (*size > *maxsize) {
151 		puts("Size exceeds partition or device limit\n");
152 		return -1;
153 	}
154 
155 print:
156 	printf("device %d ", *idx);
157 	if (*size == chipsize)
158 		puts("whole chip\n");
159 	else
160 		printf("offset 0x%llx, size 0x%llx\n",
161 		       (unsigned long long)*off, (unsigned long long)*size);
162 	return 0;
163 }
164