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