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"
18 #include <linux/cmdline-parser.h>
24 static struct cmdline_parts
*bdev_parts
;
26 static int add_part(int slot
, struct cmdline_subpart
*subpart
, void *param
)
29 struct partition_meta_info
*info
;
30 char tmp
[sizeof(info
->volname
) + 4];
31 struct parsed_partitions
*state
= (struct parsed_partitions
*)param
;
33 if (slot
>= state
->limit
)
36 put_partition(state
, slot
, subpart
->from
>> 9,
39 info
= &state
->parts
[slot
].info
;
41 label_min
= min_t(int, sizeof(info
->volname
) - 1,
42 sizeof(subpart
->name
));
43 strncpy(info
->volname
, subpart
->name
, label_min
);
44 info
->volname
[label_min
] = '\0';
46 snprintf(tmp
, sizeof(tmp
), "(%s)", info
->volname
);
47 strlcat(state
->pp_buf
, tmp
, PAGE_SIZE
);
49 state
->parts
[slot
].has_info
= true;
54 static int __init
cmdline_parts_setup(char *s
)
59 __setup("blkdevparts=", cmdline_parts_setup
);
61 static bool has_overlaps(sector_t from
, sector_t size
,
62 sector_t from2
, sector_t size2
)
64 sector_t end
= from
+ size
;
65 sector_t end2
= from2
+ size2
;
67 if (from
>= from2
&& from
< end2
)
70 if (end
> from2
&& end
<= end2
)
73 if (from2
>= from
&& from2
< end
)
76 if (end2
> from
&& end2
<= end
)
82 static inline void overlaps_warns_header(void)
84 pr_warn("Overlapping partitions are used in command line partitions.");
85 pr_warn("Don't use filesystems on overlapping partitions:");
88 static void cmdline_parts_verifier(int slot
, struct parsed_partitions
*state
)
93 for (; slot
< state
->limit
&& state
->parts
[slot
].has_info
; slot
++) {
94 for (i
= slot
+1; i
< state
->limit
&& state
->parts
[i
].has_info
;
96 if (has_overlaps(state
->parts
[slot
].from
,
97 state
->parts
[slot
].size
,
99 state
->parts
[i
].size
)) {
102 overlaps_warns_header();
104 pr_warn("%s[%llu,%llu] overlaps with "
106 state
->parts
[slot
].info
.volname
,
107 (u64
)state
->parts
[slot
].from
<< 9,
108 (u64
)state
->parts
[slot
].size
<< 9,
109 state
->parts
[i
].info
.volname
,
110 (u64
)state
->parts
[i
].from
<< 9,
111 (u64
)state
->parts
[i
].size
<< 9);
118 * Purpose: allocate cmdline partitions.
120 * -1 if unable to read the partition table
121 * 0 if this isn't our partition table
124 int cmdline_partition(struct parsed_partitions
*state
)
127 char bdev
[BDEVNAME_SIZE
];
128 struct cmdline_parts
*parts
;
132 cmdline_parts_free(&bdev_parts
);
134 if (cmdline_parts_parse(&bdev_parts
, cmdline
)) {
144 bdevname(state
->bdev
, bdev
);
145 parts
= cmdline_parts_find(bdev_parts
, bdev
);
149 disk_size
= get_capacity(state
->bdev
->bd_disk
) << 9;
151 cmdline_parts_set(parts
, disk_size
, 1, add_part
, (void *)state
);
152 cmdline_parts_verifier(1, state
);
154 strlcat(state
->pp_buf
, "\n", PAGE_SIZE
);