Skip to content

Commit 10a37fd

Browse files
nvswarrentrini
authored andcommitted
disk: get_device_and_partition() "auto" partition and cleanup
Rework get_device_and_partition() to: a) Implement a new partition ID of "auto", which requests that U-Boot search for the first "bootable" partition, and fall back to the first valid partition if none is found. This way, users don't need to specify an explicit partition in their commands. b) Make use of get_device(). c) Add parameter to indicate whether returning a whole device is acceptable, or whether a partition is mandatory. d) Make error-checking of the user's device-/partition-specification more complete. In particular, if strtoul() doesn't convert all characters, it's an error rather than just ignored. The resultant device/partition returned by the function will be as follows, based on whether the disk has a partition table (ptable) or not, and whether the calling command allows the whole device to be returned or not. (D and P are integers, P >= 1) D D: No ptable: !allow_whole_dev: error allow_whole_dev: device D ptable: device D partition 1 D:0 !allow_whole_dev: error allow_whole_dev: device D D:P No ptable: error ptable: device D partition P D:auto No ptable: !allow_whole_dev: error allow_whole_dev: device D ptable: first partition in device D with bootable flag set. If none, first valid paratition in device D. Note: In order to review this patch, it's probably easiest to simply look at the file contents post-application, rather than reading the patch itself. Signed-off-by: Rob Herring <[email protected]> [swarren: Rob implemented scanning for bootable partitions. I fixed a couple of issues there, switched the syntax to ":auto", added the error-checking rework, and ":0" syntax for the whole device] Signed-off-by: Stephen Warren <[email protected]>
1 parent 2023e60 commit 10a37fd

File tree

8 files changed

+171
-59
lines changed

8 files changed

+171
-59
lines changed

common/cmd_disk.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ int common_diskboot(cmd_tbl_t *cmdtp, const char *intf, int argc,
5454
bootstage_mark(BOOTSTAGE_ID_IDE_BOOT_DEVICE);
5555

5656
part = get_device_and_partition(intf, (argc == 3) ? argv[2] : NULL,
57-
&dev_desc, &info);
57+
&dev_desc, &info, 1);
5858
if (part < 0) {
5959
bootstage_error(BOOTSTAGE_ID_IDE_TYPE);
6060
return 1;

common/cmd_ext4.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ int do_ext4_write(cmd_tbl_t *cmdtp, int flag, int argc,
8787
if (argc < 6)
8888
return cmd_usage(cmdtp);
8989

90-
part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info);
90+
part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1);
9191
if (part < 0)
9292
return 1;
9393

common/cmd_ext_common.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ int do_ext_load(cmd_tbl_t *cmdtp, int flag, int argc,
108108
return 1;
109109
}
110110

111-
part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info);
111+
part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1);
112112
if (part < 0)
113113
return 1;
114114

@@ -166,7 +166,7 @@ int do_ext_ls(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
166166
if (argc < 2)
167167
return cmd_usage(cmdtp);
168168

169-
part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info);
169+
part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1);
170170
if (part < 0)
171171
return 1;
172172

common/cmd_fat.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ int do_fat_fsload (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
4949
return 1;
5050
}
5151

52-
part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info);
52+
part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1);
5353
if (part < 0)
5454
return 1;
5555

@@ -101,7 +101,7 @@ int do_fat_ls (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
101101
return 0;
102102
}
103103

104-
part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info);
104+
part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1);
105105
if (part < 0)
106106
return 1;
107107

@@ -139,7 +139,7 @@ int do_fat_fsinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
139139
return 0;
140140
}
141141

142-
part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info);
142+
part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1);
143143
if (part < 0)
144144
return 1;
145145

@@ -175,7 +175,7 @@ static int do_fat_fswrite(cmd_tbl_t *cmdtp, int flag,
175175
if (argc < 5)
176176
return cmd_usage(cmdtp);
177177

178-
part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info);
178+
part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1);
179179
if (part < 0)
180180
return 1;
181181

common/cmd_reiser.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ int do_reiserls (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
5757
if (argc < 3)
5858
return CMD_RET_USAGE;
5959

60-
part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info);
60+
part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1);
6161
if (part < 0)
6262
return 1;
6363

@@ -140,7 +140,7 @@ int do_reiserload (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
140140
return 1;
141141
}
142142

143-
part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info);
143+
part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1);
144144
if (part < 0)
145145
return 1;
146146

common/cmd_zfs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ static int do_zfs_load(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
9494
return 1;
9595
}
9696

97-
part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info);
97+
part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1);
9898
if (part < 0)
9999
return 1;
100100

@@ -160,7 +160,7 @@ static int do_zfs_ls(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
160160
if (argc == 4)
161161
filename = argv[3];
162162

163-
part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info);
163+
part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1);
164164
if (part < 0)
165165
return 1;
166166

disk/part.c

Lines changed: 154 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <common.h>
2525
#include <command.h>
2626
#include <ide.h>
27+
#include <malloc.h>
2728
#include <part.h>
2829

2930
#undef PART_DEBUG
@@ -465,66 +466,176 @@ int get_device(const char *ifname, const char *dev_str,
465466
return dev;
466467
}
467468

468-
int get_device_and_partition(const char *ifname, const char *dev_str,
469+
#define PART_UNSPECIFIED -2
470+
#define PART_AUTO -1
471+
#define MAX_SEARCH_PARTITIONS 16
472+
int get_device_and_partition(const char *ifname, const char *dev_part_str,
469473
block_dev_desc_t **dev_desc,
470-
disk_partition_t *info)
474+
disk_partition_t *info, int allow_whole_dev)
471475
{
472-
int ret;
473-
char *ep;
476+
int ret = -1;
477+
const char *part_str;
478+
char *dup_str = NULL;
479+
const char *dev_str;
474480
int dev;
475-
block_dev_desc_t *desc;
476-
int part = 0;
477-
char *part_str;
478-
479-
if (dev_str)
480-
dev = simple_strtoul(dev_str, &ep, 16);
481-
482-
if (!dev_str || (dev_str == ep)) {
483-
dev_str = getenv("bootdevice");
484-
if (dev_str)
485-
dev = simple_strtoul(dev_str, &ep, 16);
486-
if (!dev_str || (dev_str == ep))
487-
goto err;
481+
char *ep;
482+
int p;
483+
int part;
484+
disk_partition_t tmpinfo;
485+
486+
/* If no dev_part_str, use bootdevice environment variable */
487+
if (!dev_part_str)
488+
dev_part_str = getenv("bootdevice");
489+
490+
/* If still no dev_part_str, it's an error */
491+
if (!dev_part_str) {
492+
printf("** No device specified **\n");
493+
goto cleanup;
494+
}
495+
496+
/* Separate device and partition ID specification */
497+
part_str = strchr(dev_part_str, ':');
498+
if (part_str) {
499+
dup_str = strdup(dev_part_str);
500+
dup_str[part_str - dev_part_str] = 0;
501+
dev_str = dup_str;
502+
part_str++;
503+
} else {
504+
dev_str = dev_part_str;
488505
}
489506

490-
desc = get_dev(ifname, dev);
491-
if (!desc || (desc->type == DEV_TYPE_UNKNOWN))
492-
goto err;
507+
/* Look up the device */
508+
dev = get_device(ifname, dev_str, dev_desc);
509+
if (dev < 0)
510+
goto cleanup;
511+
512+
/* Convert partition ID string to number */
513+
if (!part_str || !*part_str) {
514+
part = PART_UNSPECIFIED;
515+
} else if (!strcmp(part_str, "auto")) {
516+
part = PART_AUTO;
517+
} else {
518+
/* Something specified -> use exactly that */
519+
part = (int)simple_strtoul(part_str, &ep, 16);
520+
/*
521+
* Less than whole string converted,
522+
* or request for whole device, but caller requires partition.
523+
*/
524+
if (*ep || (part == 0 && !allow_whole_dev)) {
525+
printf("** Bad partition specification %s %s **\n",
526+
ifname, dev_part_str);
527+
goto cleanup;
528+
}
529+
}
530+
531+
/*
532+
* No partition table on device,
533+
* or user requested partition 0 (entire device).
534+
*/
535+
if (((*dev_desc)->part_type == PART_TYPE_UNKNOWN) ||
536+
(part == 0)) {
537+
if (!(*dev_desc)->lba) {
538+
printf("** Bad device size - %s %s **\n", ifname,
539+
dev_str);
540+
goto cleanup;
541+
}
493542

494-
if (desc->part_type == PART_TYPE_UNKNOWN) {
495-
/* disk doesn't use partition table */
496-
if (!desc->lba) {
497-
printf("**Bad disk size - %s %d:0 **\n", ifname, dev);
498-
return -1;
543+
/*
544+
* If user specified a partition ID other than 0,
545+
* or the calling command only accepts partitions,
546+
* it's an error.
547+
*/
548+
if ((part > 0) || (!allow_whole_dev)) {
549+
printf("** No partition table - %s %s **\n", ifname,
550+
dev_str);
551+
goto cleanup;
499552
}
553+
500554
info->start = 0;
501-
info->size = desc->lba;
502-
info->blksz = desc->blksz;
555+
info->size = (*dev_desc)->lba;
556+
info->blksz = (*dev_desc)->blksz;
557+
info->bootable = 0;
558+
#ifdef CONFIG_PARTITION_UUIDS
559+
info->uuid[0] = 0;
560+
#endif
503561

504-
*dev_desc = desc;
505-
return 0;
562+
ret = 0;
563+
goto cleanup;
506564
}
507565

508-
part_str = strchr(dev_str, ':');
509-
if (part_str)
510-
part = (int)simple_strtoul(++part_str, NULL, 16);
511-
512-
ret = get_partition_info(desc, part, info);
513-
if (ret) {
514-
printf("** Invalid partition %d, use `dev[:part]' **\n", part);
515-
return -1;
566+
/*
567+
* Now there's known to be a partition table,
568+
* not specifying a partition means to pick partition 1.
569+
*/
570+
if (part == PART_UNSPECIFIED)
571+
part = 1;
572+
573+
/*
574+
* If user didn't specify a partition number, or did specify something
575+
* other than "auto", use that partition number directly.
576+
*/
577+
if (part != PART_AUTO) {
578+
ret = get_partition_info(*dev_desc, part, info);
579+
if (ret) {
580+
printf("** Invalid partition %d **\n", part);
581+
goto cleanup;
582+
}
583+
} else {
584+
/*
585+
* Find the first bootable partition.
586+
* If none are bootable, fall back to the first valid partition.
587+
*/
588+
part = 0;
589+
for (p = 1; p <= MAX_SEARCH_PARTITIONS; p++) {
590+
ret = get_partition_info(*dev_desc, p, info);
591+
if (ret)
592+
continue;
593+
594+
/*
595+
* First valid partition, or new better partition?
596+
* If so, save partition ID.
597+
*/
598+
if (!part || info->bootable)
599+
part = p;
600+
601+
/* Best possible partition? Stop searching. */
602+
if (info->bootable)
603+
break;
604+
605+
/*
606+
* We now need to search further for best possible.
607+
* If we what we just queried was the best so far,
608+
* save the info since we over-write it next loop.
609+
*/
610+
if (part == p)
611+
tmpinfo = *info;
612+
}
613+
/* If we found any acceptable partition */
614+
if (part) {
615+
/*
616+
* If we searched all possible partition IDs,
617+
* return the first valid partition we found.
618+
*/
619+
if (p == MAX_SEARCH_PARTITIONS + 1)
620+
*info = tmpinfo;
621+
ret = 0;
622+
} else {
623+
printf("** No valid partitions found **\n");
624+
goto cleanup;
625+
}
516626
}
517627
if (strncmp((char *)info->type, BOOT_PART_TYPE, sizeof(info->type)) != 0) {
518628
printf("** Invalid partition type \"%.32s\""
519629
" (expect \"" BOOT_PART_TYPE "\")\n",
520630
info->type);
521-
return -1;
631+
ret = -1;
632+
goto cleanup;
522633
}
523634

524-
*dev_desc = desc;
525-
return part;
635+
ret = part;
636+
goto cleanup;
526637

527-
err:
528-
puts("** Invalid boot device, use `dev[:part]' **\n");
529-
return -1;
638+
cleanup:
639+
free(dup_str);
640+
return ret;
530641
}

include/part.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,9 @@ void init_part (block_dev_desc_t *dev_desc);
114114
void dev_print(block_dev_desc_t *dev_desc);
115115
int get_device(const char *ifname, const char *dev_str,
116116
block_dev_desc_t **dev_desc);
117-
int get_device_and_partition(const char *ifname, const char *dev_str,
117+
int get_device_and_partition(const char *ifname, const char *dev_part_str,
118118
block_dev_desc_t **dev_desc,
119-
disk_partition_t *info);
119+
disk_partition_t *info, int allow_whole_dev);
120120
#else
121121
static inline block_dev_desc_t *get_dev(const char *ifname, int dev)
122122
{ return NULL; }
@@ -137,9 +137,10 @@ static inline int get_device(const char *ifname, const char *dev_str,
137137
block_dev_desc_t **dev_desc)
138138
{ return -1; }
139139
static inline int get_device_and_partition(const char *ifname,
140-
const char *dev_str,
140+
const char *dev_part_str,
141141
block_dev_desc_t **dev_desc,
142-
disk_partition_t *info)
142+
disk_partition_t *info,
143+
int allow_whole_dev)
143144
{ *dev_desc = NULL; return -1; }
144145
#endif
145146

0 commit comments

Comments
 (0)