[U-Boot] [RFC PATCH 0/5] add bootable partition support

From: Rob Herring rob.herring@calxeda.com
The primary goal of this series is to enable using the 1st bootable partition as the default partition for disk boot related commands. Every command that takes a "<dev>[:<part>]" option duplicates the same parsing code, so this series consolidates the parsing code to a single function.
There are obviously other block device commands that need to be converted still. I will do these once there is some basic agreement on the initial support.
Rob
Rob Herring (5): disk/part: check bootable flag for DOS partitions disk/part: introduce get_device_and_partition cmd_ext2: use common get_device_and_partition function cmd_fat: use common get_device_and_partition function cmd_scsi: use common get_device_and_partition function
common/cmd_ext2.c | 71 +++++++++++---------------------------------------- common/cmd_fat.c | 72 +++++++++++++++++++--------------------------------- common/cmd_scsi.c | 58 ++++++++---------------------------------- disk/part.c | 60 ++++++++++++++++++++++++++++++++++++++++++++ disk/part_dos.c | 11 ++++++- include/part.h | 5 +++ 6 files changed, 127 insertions(+), 150 deletions(-)

From: Rob Herring rob.herring@calxeda.com
Determine which partitions are bootable/active. In the partition listing, print "Boot" for partitions with the bootable/active flag set.
Signed-off-by: Rob Herring rob.herring@calxeda.com --- disk/part_dos.c | 11 +++++++++-- include/part.h | 1 + 2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/disk/part_dos.c b/disk/part_dos.c index b5bcb37..1620c1d 100644 --- a/disk/part_dos.c +++ b/disk/part_dos.c @@ -61,14 +61,20 @@ static inline int is_extended(int part_type) part_type == 0x85); }
+static inline int is_bootable(dos_partition_t *p) +{ + return p->boot_ind == 0x80; +} + static void print_one_part (dos_partition_t *p, int ext_part_sector, int part_num) { int lba_start = ext_part_sector + le32_to_int (p->start4); int lba_size = le32_to_int (p->size4);
- printf ("%5d\t\t%10d\t%10d\t%2x%s\n", + printf("%5d\t\t%10d\t%10d\t%2x%s%s\n", part_num, lba_start, lba_size, p->sys_ind, - (is_extended (p->sys_ind) ? " Extd" : "")); + (is_extended(p->sys_ind) ? " Extd" : ""), + (is_bootable(p) ? " Boot" : "")); }
static int test_block_type(unsigned char *buffer) @@ -223,6 +229,7 @@ static int get_partition_info_extended (block_dev_desc_t *dev_desc, int ext_part } /* sprintf(info->type, "%d, pt->sys_ind); */ sprintf ((char *)info->type, "U-Boot"); + info->bootable = is_bootable(pt); return 0; }
diff --git a/include/part.h b/include/part.h index 1827767..79a3493 100644 --- a/include/part.h +++ b/include/part.h @@ -93,6 +93,7 @@ typedef struct disk_partition { ulong blksz; /* block size in bytes */ uchar name[32]; /* partition name */ uchar type[32]; /* string type description */ + int bootable; /* Active/Bootable flag is set */ } disk_partition_t;
/* Misc _get_dev functions */

From: Rob Herring rob.herring@calxeda.com
All block device related commands (scsiboot, fatload, ext2ls, etc.) have simliar duplicated device and partition parsing and selection code. This adds a common function to replace various implementations.
The new function has some enhancements over current versions. If no device or partition is specified on the command line, the bootdevice env variable will be used (scsiboot does this). If the partition is not specified and the device has partitions, then the first bootable partition will be used.
Signed-off-by: Rob Herring rob.herring@calxeda.com --- disk/part.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/part.h | 4 +++ 2 files changed, 64 insertions(+), 0 deletions(-)
diff --git a/disk/part.c b/disk/part.c index f07a17f..e892c8d 100644 --- a/disk/part.c +++ b/disk/part.c @@ -291,6 +291,7 @@ void init_part (block_dev_desc_t * dev_desc) return; } #endif + dev_desc->part_type = PART_TYPE_UNKNOWN; }
@@ -435,4 +436,63 @@ void print_part (block_dev_desc_t * dev_desc) # error nor CONFIG_EFI_PARTITION configured! #endif
+int get_device_and_partition(const char *ifname, const char *dev_str, + block_dev_desc_t **dev_desc, + disk_partition_t *info) +{ + int ret; + char *ep; + int dev; + block_dev_desc_t *desc; + int part = 1; + int do_scan_part = 1; + char *part_str; + + if (dev_str) + dev = simple_strtoul(dev_str, &ep, 16); + + if (!dev_str || (dev_str == ep)) { + dev_str = getenv("bootdevice"); + if (dev_str) + dev = simple_strtoul(dev_str, &ep, 16); + if (!dev_str || dev_str == ep) + goto err; + } + + desc = get_dev(ifname, dev); + if (!desc || (desc->type == DEV_TYPE_UNKNOWN)) + goto err; + + if (desc->part_type == PART_TYPE_UNKNOWN) + return 0; + + part_str = strchr(dev_str, ':'); + if (part_str) { + part = (int)simple_strtoul(++part_str, NULL, 16); + do_scan_part = 0; + } + + while ((ret = get_partition_info(desc, part, info)) == 0 && + !info->bootable && do_scan_part) + part++; + + if (ret) { + puts("** Invalid partition, use `dev[:part]' **\n"); + return -1; + } + if (strncmp((char *)info->type, BOOT_PART_TYPE, sizeof(info->type)) != 0) { + printf("** Invalid partition type "%.32s"" + " (expect "" BOOT_PART_TYPE "")\n", + info->type); + return -1; + } + + *dev_desc = desc; + return part; + + err: + puts("** Invalid boot device, use `dev[:part]' **\n"); + return -1; +} + #endif diff --git a/include/part.h b/include/part.h index 79a3493..e44ca49 100644 --- a/include/part.h +++ b/include/part.h @@ -129,6 +129,10 @@ static inline void init_part (block_dev_desc_t *dev_desc) {} static inline void dev_print(block_dev_desc_t *dev_desc) {} #endif
+int get_device_and_partition(const char *ifname, const char *dev_str, + block_dev_desc_t **dev_desc, + disk_partition_t *info); + #ifdef CONFIG_MAC_PARTITION /* disk/part_mac.c */ int get_partition_info_mac (block_dev_desc_t * dev_desc, int part, disk_partition_t *info);

From: Rob Herring rob.herring@calxeda.com
Convert ext2ls and ext2load to use common device and partition parsing function.
Signed-off-by: Rob Herring rob.herring@calxeda.com --- common/cmd_ext2.c | 71 ++++++++++++----------------------------------------- 1 files changed, 16 insertions(+), 55 deletions(-)
diff --git a/common/cmd_ext2.c b/common/cmd_ext2.c index 35fb361..84dafd6 100644 --- a/common/cmd_ext2.c +++ b/common/cmd_ext2.c @@ -59,34 +59,24 @@ int do_ext2ls (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { char *filename = "/"; - int dev=0; - int part=1; + int dev; + int part; char *ep; - block_dev_desc_t *dev_desc=NULL; + block_dev_desc_t *dev_desc; + disk_partition_t info; int part_length;
- if (argc < 3) + if (argc < 2) return cmd_usage(cmdtp);
- dev = (int)simple_strtoul (argv[2], &ep, 16); - dev_desc = get_dev(argv[1],dev); - - if (dev_desc == NULL) { - printf ("\n** Block device %s %d not supported\n", argv[1], dev); + part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info); + if (part < 0) return 1; - } - - if (*ep) { - if (*ep != ':') { - puts ("\n** Invalid boot device, use `dev[:part]' **\n"); - return 1; - } - part = (int)simple_strtoul(++ep, NULL, 16); - }
if (argc == 4) filename = argv[3];
+ dev = dev_desc->dev; PRINTF("Using device %s %d:%d, directory: %s\n", argv[1], dev, part, filename);
if ((part_length = ext2fs_set_blk_dev(dev_desc, part)) == 0) { @@ -126,11 +116,11 @@ int do_ext2load (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { char *filename = NULL; char *ep; - int dev, part = 1; + int dev, part; ulong addr = 0, part_length; int filelen; disk_partition_t info; - block_dev_desc_t *dev_desc = NULL; + block_dev_desc_t *dev_desc; char buf [12]; unsigned long count; char *addr_str; @@ -171,43 +161,14 @@ int do_ext2load (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 1; }
- dev = (int)simple_strtoul (argv[2], &ep, 16); - dev_desc = get_dev(argv[1],dev); - if (dev_desc==NULL) { - printf ("** Block device %s %d not supported\n", argv[1], dev); + part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info); + if (part < 0) return 1; - } - if (*ep) { - if (*ep != ':') { - puts ("** Invalid boot device, use `dev[:part]' **\n"); - return 1; - } - part = (int)simple_strtoul(++ep, NULL, 16); - } - - PRINTF("Using device %s%d, partition %d\n", argv[1], dev, part); - - if (part != 0) { - if (get_partition_info (dev_desc, part, &info)) { - printf ("** Bad partition %d **\n", part); - return 1; - } - - if (strncmp((char *)info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0) { - printf ("** Invalid partition type "%.32s"" - " (expect "" BOOT_PART_TYPE "")\n", - info.type); - return 1; - } - printf ("Loading file "%s" " - "from %s device %d:%d (%.32s)\n", - filename, - argv[1], dev, part, info.name); - } else { - printf ("Loading file "%s" from %s device %d\n", - filename, argv[1], dev); - }
+ dev = dev_desc->dev; + printf("Loading file "%s" from %s device %d%c%c\n", + filename, argv[1], dev, + part ? ':' : ' ', part ? part + '0' : ' ');
if ((part_length = ext2fs_set_blk_dev(dev_desc, part)) == 0) { printf ("** Bad partition - %s %d:%d **\n", argv[1], dev, part);

From: Rob Herring rob.herring@calxeda.com
Convert fatload, fatls, and fatinfo to use common device and partition parsing function. With the common function "dev:part" can come from the environment and a '-' can be used in that case.
Signed-off-by: Rob Herring rob.herring@calxeda.com --- common/cmd_fat.c | 72 +++++++++++++++++++---------------------------------- 1 files changed, 26 insertions(+), 46 deletions(-)
diff --git a/common/cmd_fat.c b/common/cmd_fat.c index 0220494..be617fe 100644 --- a/common/cmd_fat.c +++ b/common/cmd_fat.c @@ -40,29 +40,21 @@ int do_fat_fsload (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) unsigned long count; char buf [12]; block_dev_desc_t *dev_desc=NULL; - int dev=0; - int part=1; + disk_partition_t info; + int part, dev; char *ep;
if (argc < 5) { - printf( "usage: fatload <interface> <dev[:part]> " + printf("usage: fatload <interface> [<dev[:part]>] " "<addr> <filename> [bytes]\n"); return 1; }
- dev = (int)simple_strtoul(argv[2], &ep, 16); - dev_desc = get_dev(argv[1],dev); - if (dev_desc == NULL) { - puts("\n** Invalid boot device **\n"); + part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info); + if (part < 0) return 1; - } - if (*ep) { - if (*ep != ':') { - puts("\n** Invalid boot device, use `dev[:part]' **\n"); - return 1; - } - part = (int)simple_strtoul(++ep, NULL, 16); - } + + dev = dev_desc->dev; if (fat_register_device(dev_desc,part)!=0) { printf("\n** Unable to use %s %d:%d for fatload **\n", argv[1], dev, part); @@ -93,7 +85,7 @@ int do_fat_fsload (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) U_BOOT_CMD( fatload, 6, 0, do_fat_fsload, "load binary file from a dos filesystem", - "<interface> <dev[:part]> <addr> <filename> [bytes]\n" + "<interface> [<dev[:part]>] <addr> <filename> [bytes]\n" " - load binary file 'filename' from 'dev' on 'interface'\n" " to address 'addr' from dos filesystem" ); @@ -106,24 +98,18 @@ int do_fat_ls (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) int part=1; char *ep; block_dev_desc_t *dev_desc=NULL; + disk_partition_t info;
- if (argc < 3) { - printf("usage: fatls <interface> <dev[:part]> [directory]\n"); + if (argc < 2) { + printf("usage: fatls <interface> [<dev[:part]>] [directory]\n"); return 0; } - dev = (int)simple_strtoul(argv[2], &ep, 16); - dev_desc = get_dev(argv[1],dev); - if (dev_desc == NULL) { - puts("\n** Invalid boot device **\n"); + + part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info); + if (part < 0) return 1; - } - if (*ep) { - if (*ep != ':') { - puts("\n** Invalid boot device, use `dev[:part]' **\n"); - return 1; - } - part = (int)simple_strtoul(++ep, NULL, 16); - } + + dev = dev_desc->dev; if (fat_register_device(dev_desc,part)!=0) { printf("\n** Unable to use %s %d:%d for fatls **\n", argv[1], dev, part); @@ -142,7 +128,7 @@ int do_fat_ls (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) U_BOOT_CMD( fatls, 4, 1, do_fat_ls, "list files in a directory (default /)", - "<interface> <dev[:part]> [directory]\n" + "<interface> [<dev[:part]>] [directory]\n" " - list files from 'dev' on 'interface' in a 'directory'" );
@@ -151,25 +137,19 @@ int do_fat_fsinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) int dev=0; int part=1; char *ep; - block_dev_desc_t *dev_desc=NULL; + block_dev_desc_t *dev_desc; + disk_partition_t info;
if (argc < 2) { - printf("usage: fatinfo <interface> <dev[:part]>\n"); + printf("usage: fatinfo <interface> [<dev[:part]>]\n"); return 0; } - dev = (int)simple_strtoul(argv[2], &ep, 16); - dev_desc = get_dev(argv[1],dev); - if (dev_desc == NULL) { - puts("\n** Invalid boot device **\n"); + + part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info); + if (part < 0) return 1; - } - if (*ep) { - if (*ep != ':') { - puts("\n** Invalid boot device, use `dev[:part]' **\n"); - return 1; - } - part = (int)simple_strtoul(++ep, NULL, 16); - } + + dev = dev_desc->dev; if (fat_register_device(dev_desc,part)!=0) { printf("\n** Unable to use %s %d:%d for fatinfo **\n", argv[1], dev, part); @@ -181,6 +161,6 @@ int do_fat_fsinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) U_BOOT_CMD( fatinfo, 3, 1, do_fat_fsinfo, "print information about filesystem", - "<interface> <dev[:part]>\n" + "<interface> [<dev[:part]>]\n" " - print information about filesystem from 'dev' on 'interface'" );

From: Rob Herring rob.herring@calxeda.com
Convert scsiboot to use common device and partition parsing function.
Signed-off-by: Rob Herring rob.herring@calxeda.com --- common/cmd_scsi.c | 58 ++++++++++------------------------------------------ 1 files changed, 11 insertions(+), 47 deletions(-)
diff --git a/common/cmd_scsi.c b/common/cmd_scsi.c index fa10751..dcf8b84 100644 --- a/common/cmd_scsi.c +++ b/common/cmd_scsi.c @@ -206,64 +206,28 @@ block_dev_desc_t * scsi_get_dev(int dev) */ int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - char *boot_device = NULL; - char *ep; - int dev, part = 0; - ulong addr, cnt; + int dev, part; + ulong addr = CONFIG_SYS_LOAD_ADDR; + ulong cnt; + block_dev_desc_t *dev_desc; disk_partition_t info; image_header_t *hdr; #if defined(CONFIG_FIT) const void *fit_hdr = NULL; #endif
- switch (argc) { - case 1: - addr = CONFIG_SYS_LOAD_ADDR; - boot_device = getenv ("bootdevice"); - break; - case 2: - addr = simple_strtoul(argv[1], NULL, 16); - boot_device = getenv ("bootdevice"); - break; - case 3: - addr = simple_strtoul(argv[1], NULL, 16); - boot_device = argv[2]; - break; - default: + if (argc > 3) return cmd_usage(cmdtp); - }
- if (!boot_device) { - puts ("\n** No boot device **\n"); - return 1; - } - - dev = simple_strtoul(boot_device, &ep, 16); - printf("booting from dev %d\n",dev); - if (scsi_dev_desc[dev].type == DEV_TYPE_UNKNOWN) { - printf ("\n** Device %d not available\n", dev); - return 1; - } + if (argc > 1) + addr = simple_strtoul(argv[1], NULL, 16);
- if (*ep) { - if (*ep != ':') { - puts ("\n** Invalid boot device, use `dev[:part]' **\n"); - return 1; - } - part = simple_strtoul(++ep, NULL, 16); - } - if (get_partition_info (&scsi_dev_desc[dev], part, &info)) { - printf("error reading partinfo\n"); + part = get_device_and_partition("scsi", (argc == 3) ? argv[2] : NULL, + &dev_desc, &info); + if (part < 0) return 1; - } - if ((strncmp((char *)(info.type), BOOT_PART_TYPE, sizeof(info.type)) != 0) && - (strncmp((char *)(info.type), BOOT_PART_COMP, sizeof(info.type)) != 0)) { - printf ("\n** Invalid partition type "%.32s"" - " (expect "" BOOT_PART_TYPE "")\n", - info.type); - return 1; - }
+ dev = dev_desc->dev; printf ("\nLoading from SCSI device %d, partition %d: " "Name: %.32s Type: %.32s\n", dev, part, info.name, info.type);
participants (1)
-
Rob Herring