1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2013 HUAWEI
4 * Author: Cai Zhiyong <caizhiyong@huawei.com>
6 * Read block device partition table from the command line.
7 * Typically used for fixed block (eMMC) embedded devices.
8 * It has no MBR, so saves storage space. Bootloader can be easily accessed
9 * by absolute address of data on the block device.
10 * Users can easily change the partition.
12 * The format for the command line is just like mtdparts.
14 * For further information, see "Documentation/block/cmdline-partition.rst"
17 #include <linux/blkdev.h>
19 #include <linux/slab.h>
24 #define PF_RDONLY 0x01 /* Device is read only */
25 #define PF_POWERUP_LOCK 0x02 /* Always locked after reset */
27 struct cmdline_subpart
{
28 char name
[BDEVNAME_SIZE
]; /* partition name, such as 'rootfs' */
32 struct cmdline_subpart
*next_subpart
;
35 struct cmdline_parts
{
36 char name
[BDEVNAME_SIZE
]; /* block device, such as 'mmcblk0' */
37 unsigned int nr_subparts
;
38 struct cmdline_subpart
*subpart
;
39 struct cmdline_parts
*next_parts
;
42 static int parse_subpart(struct cmdline_subpart
**subpart
, char *partdef
)
45 struct cmdline_subpart
*new_subpart
;
49 new_subpart
= kzalloc(sizeof(struct cmdline_subpart
), GFP_KERNEL
);
53 if (*partdef
== '-') {
54 new_subpart
->size
= (sector_t
)(~0ULL);
57 new_subpart
->size
= (sector_t
)memparse(partdef
, &partdef
);
58 if (new_subpart
->size
< (sector_t
)PAGE_SIZE
) {
59 pr_warn("cmdline partition size is invalid.");
65 if (*partdef
== '@') {
67 new_subpart
->from
= (sector_t
)memparse(partdef
, &partdef
);
69 new_subpart
->from
= (sector_t
)(~0ULL);
72 if (*partdef
== '(') {
74 char *next
= strsep(&partdef
, ")");
77 pr_warn("cmdline partition format is invalid.");
82 strscpy(new_subpart
->name
, next
, sizeof(new_subpart
->name
));
84 new_subpart
->name
[0] = '\0';
86 new_subpart
->flags
= 0;
88 if (!strncmp(partdef
, "ro", 2)) {
89 new_subpart
->flags
|= PF_RDONLY
;
93 if (!strncmp(partdef
, "lk", 2)) {
94 new_subpart
->flags
|= PF_POWERUP_LOCK
;
98 *subpart
= new_subpart
;
105 static void free_subpart(struct cmdline_parts
*parts
)
107 struct cmdline_subpart
*subpart
;
109 while (parts
->subpart
) {
110 subpart
= parts
->subpart
;
111 parts
->subpart
= subpart
->next_subpart
;
116 static int parse_parts(struct cmdline_parts
**parts
, char *bdevdef
)
120 struct cmdline_subpart
**next_subpart
;
121 struct cmdline_parts
*newparts
;
125 newparts
= kzalloc(sizeof(struct cmdline_parts
), GFP_KERNEL
);
129 next
= strsep(&bdevdef
, ":");
131 pr_warn("cmdline partition has no block device.");
135 strscpy(newparts
->name
, next
, sizeof(newparts
->name
));
136 newparts
->nr_subparts
= 0;
138 next_subpart
= &newparts
->subpart
;
140 while ((next
= strsep(&bdevdef
, ","))) {
141 ret
= parse_subpart(next_subpart
, next
);
145 newparts
->nr_subparts
++;
146 next_subpart
= &(*next_subpart
)->next_subpart
;
149 if (!newparts
->subpart
) {
150 pr_warn("cmdline partition has no valid partition.");
159 free_subpart(newparts
);
164 static void cmdline_parts_free(struct cmdline_parts
**parts
)
166 struct cmdline_parts
*next_parts
;
169 next_parts
= (*parts
)->next_parts
;
170 free_subpart(*parts
);
176 static int cmdline_parts_parse(struct cmdline_parts
**parts
,
183 struct cmdline_parts
**next_parts
;
187 pbuf
= buf
= kstrdup(cmdline
, GFP_KERNEL
);
193 while ((next
= strsep(&pbuf
, ";"))) {
194 ret
= parse_parts(next_parts
, next
);
198 next_parts
= &(*next_parts
)->next_parts
;
202 pr_warn("cmdline partition has no valid partition.");
213 cmdline_parts_free(parts
);
217 static struct cmdline_parts
*cmdline_parts_find(struct cmdline_parts
*parts
,
220 while (parts
&& strncmp(bdev
, parts
->name
, sizeof(parts
->name
)))
221 parts
= parts
->next_parts
;
225 static char *cmdline
;
226 static struct cmdline_parts
*bdev_parts
;
228 static int add_part(int slot
, struct cmdline_subpart
*subpart
,
229 struct parsed_partitions
*state
)
231 struct partition_meta_info
*info
;
232 char tmp
[sizeof(info
->volname
) + 4];
234 if (slot
>= state
->limit
)
237 put_partition(state
, slot
, subpart
->from
>> 9,
240 if (subpart
->flags
& PF_RDONLY
)
241 state
->parts
[slot
].flags
|= ADDPART_FLAG_READONLY
;
243 info
= &state
->parts
[slot
].info
;
245 strscpy(info
->volname
, subpart
->name
, sizeof(info
->volname
));
247 snprintf(tmp
, sizeof(tmp
), "(%s)", info
->volname
);
248 strlcat(state
->pp_buf
, tmp
, PAGE_SIZE
);
250 state
->parts
[slot
].has_info
= true;
255 static int cmdline_parts_set(struct cmdline_parts
*parts
, sector_t disk_size
,
256 struct parsed_partitions
*state
)
259 struct cmdline_subpart
*subpart
;
262 for (subpart
= parts
->subpart
; subpart
;
263 subpart
= subpart
->next_subpart
, slot
++) {
264 if (subpart
->from
== (sector_t
)(~0ULL))
265 subpart
->from
= from
;
267 from
= subpart
->from
;
269 if (from
>= disk_size
)
272 if (subpart
->size
> (disk_size
- from
))
273 subpart
->size
= disk_size
- from
;
275 from
+= subpart
->size
;
277 if (add_part(slot
, subpart
, state
))
284 static int __init
cmdline_parts_setup(char *s
)
289 __setup("blkdevparts=", cmdline_parts_setup
);
291 static bool has_overlaps(sector_t from
, sector_t size
,
292 sector_t from2
, sector_t size2
)
294 sector_t end
= from
+ size
;
295 sector_t end2
= from2
+ size2
;
297 if (from
>= from2
&& from
< end2
)
300 if (end
> from2
&& end
<= end2
)
303 if (from2
>= from
&& from2
< end
)
306 if (end2
> from
&& end2
<= end
)
312 static inline void overlaps_warns_header(void)
314 pr_warn("Overlapping partitions are used in command line partitions.");
315 pr_warn("Don't use filesystems on overlapping partitions:");
318 static void cmdline_parts_verifier(int slot
, struct parsed_partitions
*state
)
323 for (; slot
< state
->limit
&& state
->parts
[slot
].has_info
; slot
++) {
324 for (i
= slot
+1; i
< state
->limit
&& state
->parts
[i
].has_info
;
326 if (has_overlaps(state
->parts
[slot
].from
,
327 state
->parts
[slot
].size
,
328 state
->parts
[i
].from
,
329 state
->parts
[i
].size
)) {
332 overlaps_warns_header();
334 pr_warn("%s[%llu,%llu] overlaps with "
336 state
->parts
[slot
].info
.volname
,
337 (u64
)state
->parts
[slot
].from
<< 9,
338 (u64
)state
->parts
[slot
].size
<< 9,
339 state
->parts
[i
].info
.volname
,
340 (u64
)state
->parts
[i
].from
<< 9,
341 (u64
)state
->parts
[i
].size
<< 9);
348 * Purpose: allocate cmdline partitions.
350 * -1 if unable to read the partition table
351 * 0 if this isn't our partition table
354 int cmdline_partition(struct parsed_partitions
*state
)
357 struct cmdline_parts
*parts
;
361 cmdline_parts_free(&bdev_parts
);
363 if (cmdline_parts_parse(&bdev_parts
, cmdline
)) {
373 parts
= cmdline_parts_find(bdev_parts
, state
->disk
->disk_name
);
377 disk_size
= get_capacity(state
->disk
) << 9;
379 cmdline_parts_set(parts
, disk_size
, state
);
380 cmdline_parts_verifier(1, state
);
382 strlcat(state
->pp_buf
, "\n", PAGE_SIZE
);