1 // SPDX-License-Identifier: GPL-2.0
3 * Parse command line, get partition information
5 * Written by Cai Zhiyong <caizhiyong@huawei.com>
8 #include <linux/export.h>
9 #include <linux/cmdline-parser.h>
11 static int parse_subpart(struct cmdline_subpart
**subpart
, char *partdef
)
14 struct cmdline_subpart
*new_subpart
;
18 new_subpart
= kzalloc(sizeof(struct cmdline_subpart
), GFP_KERNEL
);
22 if (*partdef
== '-') {
23 new_subpart
->size
= (sector_t
)(~0ULL);
26 new_subpart
->size
= (sector_t
)memparse(partdef
, &partdef
);
27 if (new_subpart
->size
< (sector_t
)PAGE_SIZE
) {
28 pr_warn("cmdline partition size is invalid.");
34 if (*partdef
== '@') {
36 new_subpart
->from
= (sector_t
)memparse(partdef
, &partdef
);
38 new_subpart
->from
= (sector_t
)(~0ULL);
41 if (*partdef
== '(') {
43 char *next
= strchr(++partdef
, ')');
46 pr_warn("cmdline partition format is invalid.");
51 length
= min_t(int, next
- partdef
,
52 sizeof(new_subpart
->name
) - 1);
53 strncpy(new_subpart
->name
, partdef
, length
);
54 new_subpart
->name
[length
] = '\0';
58 new_subpart
->name
[0] = '\0';
60 new_subpart
->flags
= 0;
62 if (!strncmp(partdef
, "ro", 2)) {
63 new_subpart
->flags
|= PF_RDONLY
;
67 if (!strncmp(partdef
, "lk", 2)) {
68 new_subpart
->flags
|= PF_POWERUP_LOCK
;
72 *subpart
= new_subpart
;
79 static void free_subpart(struct cmdline_parts
*parts
)
81 struct cmdline_subpart
*subpart
;
83 while (parts
->subpart
) {
84 subpart
= parts
->subpart
;
85 parts
->subpart
= subpart
->next_subpart
;
90 static int parse_parts(struct cmdline_parts
**parts
, const char *bdevdef
)
95 struct cmdline_subpart
**next_subpart
;
96 struct cmdline_parts
*newparts
;
97 char buf
[BDEVNAME_SIZE
+ 32 + 4];
101 newparts
= kzalloc(sizeof(struct cmdline_parts
), GFP_KERNEL
);
105 next
= strchr(bdevdef
, ':');
107 pr_warn("cmdline partition has no block device.");
111 length
= min_t(int, next
- bdevdef
, sizeof(newparts
->name
) - 1);
112 strncpy(newparts
->name
, bdevdef
, length
);
113 newparts
->name
[length
] = '\0';
114 newparts
->nr_subparts
= 0;
116 next_subpart
= &newparts
->subpart
;
118 while (next
&& *(++next
)) {
120 next
= strchr(bdevdef
, ',');
122 length
= (!next
) ? (sizeof(buf
) - 1) :
123 min_t(int, next
- bdevdef
, sizeof(buf
) - 1);
125 strncpy(buf
, bdevdef
, length
);
128 ret
= parse_subpart(next_subpart
, buf
);
132 newparts
->nr_subparts
++;
133 next_subpart
= &(*next_subpart
)->next_subpart
;
136 if (!newparts
->subpart
) {
137 pr_warn("cmdline partition has no valid partition.");
146 free_subpart(newparts
);
151 void cmdline_parts_free(struct cmdline_parts
**parts
)
153 struct cmdline_parts
*next_parts
;
156 next_parts
= (*parts
)->next_parts
;
157 free_subpart(*parts
);
162 EXPORT_SYMBOL(cmdline_parts_free
);
164 int cmdline_parts_parse(struct cmdline_parts
**parts
, const char *cmdline
)
170 struct cmdline_parts
**next_parts
;
174 next
= pbuf
= buf
= kstrdup(cmdline
, GFP_KERNEL
);
180 while (next
&& *pbuf
) {
181 next
= strchr(pbuf
, ';');
185 ret
= parse_parts(next_parts
, pbuf
);
192 next_parts
= &(*next_parts
)->next_parts
;
196 pr_warn("cmdline partition has no valid partition.");
207 cmdline_parts_free(parts
);
210 EXPORT_SYMBOL(cmdline_parts_parse
);
212 struct cmdline_parts
*cmdline_parts_find(struct cmdline_parts
*parts
,
215 while (parts
&& strncmp(bdev
, parts
->name
, sizeof(parts
->name
)))
216 parts
= parts
->next_parts
;
219 EXPORT_SYMBOL(cmdline_parts_find
);
224 * 1 can not add so many partitions.
226 int cmdline_parts_set(struct cmdline_parts
*parts
, sector_t disk_size
,
228 int (*add_part
)(int, struct cmdline_subpart
*, void *),
232 struct cmdline_subpart
*subpart
;
234 for (subpart
= parts
->subpart
; subpart
;
235 subpart
= subpart
->next_subpart
, slot
++) {
236 if (subpart
->from
== (sector_t
)(~0ULL))
237 subpart
->from
= from
;
239 from
= subpart
->from
;
241 if (from
>= disk_size
)
244 if (subpart
->size
> (disk_size
- from
))
245 subpart
->size
= disk_size
- from
;
247 from
+= subpart
->size
;
249 if (add_part(slot
, subpart
, param
))
255 EXPORT_SYMBOL(cmdline_parts_set
);