1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2013 HUAWEI 4 * Author: Cai Zhiyong <caizhiyong@huawei.com> 5 * 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. 11 * 12 * The format for the command line is just like mtdparts. 13 * 14 * For further information, see "Documentation/block/cmdline-partition.txt" 15 * 16 */ 17 18 #include <linux/cmdline-parser.h> 19 20 #include "check.h" 21 #include "cmdline.h" 22 23 static char *cmdline; 24 static struct cmdline_parts *bdev_parts; 25 26 static int add_part(int slot, struct cmdline_subpart *subpart, void *param) 27 { 28 int label_min; 29 struct partition_meta_info *info; 30 char tmp[sizeof(info->volname) + 4]; 31 struct parsed_partitions *state = (struct parsed_partitions *)param; 32 33 if (slot >= state->limit) 34 return 1; 35 36 put_partition(state, slot, subpart->from >> 9, 37 subpart->size >> 9); 38 39 info = &state->parts[slot].info; 40 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'; 45 46 snprintf(tmp, sizeof(tmp), "(%s)", info->volname); 47 strlcat(state->pp_buf, tmp, PAGE_SIZE); 48 49 state->parts[slot].has_info = true; 50 51 return 0; 52 } 53 54 static int __init cmdline_parts_setup(char *s) 55 { 56 cmdline = s; 57 return 1; 58 } 59 __setup("blkdevparts=", cmdline_parts_setup); 60 61 /* 62 * Purpose: allocate cmdline partitions. 63 * Returns: 64 * -1 if unable to read the partition table 65 * 0 if this isn't our partition table 66 * 1 if successful 67 */ 68 int cmdline_partition(struct parsed_partitions *state) 69 { 70 sector_t disk_size; 71 char bdev[BDEVNAME_SIZE]; 72 struct cmdline_parts *parts; 73 74 if (cmdline) { 75 if (bdev_parts) 76 cmdline_parts_free(&bdev_parts); 77 78 if (cmdline_parts_parse(&bdev_parts, cmdline)) { 79 cmdline = NULL; 80 return -1; 81 } 82 cmdline = NULL; 83 } 84 85 if (!bdev_parts) 86 return 0; 87 88 bdevname(state->bdev, bdev); 89 parts = cmdline_parts_find(bdev_parts, bdev); 90 if (!parts) 91 return 0; 92 93 disk_size = get_capacity(state->bdev->bd_disk) << 9; 94 95 cmdline_parts_set(parts, disk_size, 1, add_part, (void *)state); 96 97 strlcat(state->pp_buf, "\n", PAGE_SIZE); 98 99 return 1; 100 } 101