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