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>
23 static struct cmdline_parts
*bdev_parts
;
25 static int add_part(int slot
, struct cmdline_subpart
*subpart
, void *param
)
28 struct partition_meta_info
*info
;
29 char tmp
[sizeof(info
->volname
) + 4];
30 struct parsed_partitions
*state
= (struct parsed_partitions
*)param
;
32 if (slot
>= state
->limit
)
35 put_partition(state
, slot
, subpart
->from
>> 9,
38 info
= &state
->parts
[slot
].info
;
40 label_min
= min_t(int, sizeof(info
->volname
) - 1,
41 sizeof(subpart
->name
));
42 strncpy(info
->volname
, subpart
->name
, label_min
);
43 info
->volname
[label_min
] = '\0';
45 snprintf(tmp
, sizeof(tmp
), "(%s)", info
->volname
);
46 strlcat(state
->pp_buf
, tmp
, PAGE_SIZE
);
48 state
->parts
[slot
].has_info
= true;
53 static int __init
cmdline_parts_setup(char *s
)
58 __setup("blkdevparts=", cmdline_parts_setup
);
60 static bool has_overlaps(sector_t from
, sector_t size
,
61 sector_t from2
, sector_t size2
)
63 sector_t end
= from
+ size
;
64 sector_t end2
= from2
+ size2
;
66 if (from
>= from2
&& from
< end2
)
69 if (end
> from2
&& end
<= end2
)
72 if (from2
>= from
&& from2
< end
)
75 if (end2
> from
&& end2
<= end
)
81 static inline void overlaps_warns_header(void)
83 pr_warn("Overlapping partitions are used in command line partitions.");
84 pr_warn("Don't use filesystems on overlapping partitions:");
87 static void cmdline_parts_verifier(int slot
, struct parsed_partitions
*state
)
92 for (; slot
< state
->limit
&& state
->parts
[slot
].has_info
; slot
++) {
93 for (i
= slot
+1; i
< state
->limit
&& state
->parts
[i
].has_info
;
95 if (has_overlaps(state
->parts
[slot
].from
,
96 state
->parts
[slot
].size
,
98 state
->parts
[i
].size
)) {
101 overlaps_warns_header();
103 pr_warn("%s[%llu,%llu] overlaps with "
105 state
->parts
[slot
].info
.volname
,
106 (u64
)state
->parts
[slot
].from
<< 9,
107 (u64
)state
->parts
[slot
].size
<< 9,
108 state
->parts
[i
].info
.volname
,
109 (u64
)state
->parts
[i
].from
<< 9,
110 (u64
)state
->parts
[i
].size
<< 9);
117 * Purpose: allocate cmdline partitions.
119 * -1 if unable to read the partition table
120 * 0 if this isn't our partition table
123 int cmdline_partition(struct parsed_partitions
*state
)
126 char bdev
[BDEVNAME_SIZE
];
127 struct cmdline_parts
*parts
;
131 cmdline_parts_free(&bdev_parts
);
133 if (cmdline_parts_parse(&bdev_parts
, cmdline
)) {
143 bdevname(state
->bdev
, bdev
);
144 parts
= cmdline_parts_find(bdev_parts
, bdev
);
148 disk_size
= get_capacity(state
->bdev
->bd_disk
) << 9;
150 cmdline_parts_set(parts
, disk_size
, 1, add_part
, (void *)state
);
151 cmdline_parts_verifier(1, state
);
153 strlcat(state
->pp_buf
, "\n", PAGE_SIZE
);