diff options
-rw-r--r-- | boot/bootdev-uclass.c | 35 | ||||
-rw-r--r-- | boot/bootflow.c | 3 | ||||
-rw-r--r-- | doc/develop/bootstd.rst | 4 | ||||
-rw-r--r-- | include/bootflow.h | 3 |
4 files changed, 43 insertions, 2 deletions
diff --git a/boot/bootdev-uclass.c b/boot/bootdev-uclass.c index 0fa6dad8b11..46815ea2fdb 100644 --- a/boot/bootdev-uclass.c +++ b/boot/bootdev-uclass.c @@ -172,8 +172,10 @@ int bootdev_find_in_blk(struct udevice *dev, struct udevice *blk, */ iter->max_part = MAX_PART_PER_BOOTDEV; - /* If this is the whole disk, check if we have bootable partitions */ - if (!iter->part) { + if (iter->flags & BOOTFLOWIF_SINGLE_PARTITION) { + /* a particular partition was specified, scan it without checking */ + } else if (!iter->part) { + /* This is the whole disk, check if we have bootable partitions */ iter->first_bootable = part_get_bootable(desc); log_debug("checking bootable=%d\n", iter->first_bootable); } else if (allow_any_part) { @@ -710,8 +712,37 @@ int bootdev_setup_iter(struct bootflow_iter *iter, const char *label, struct udevice *bootstd, *dev = NULL; bool show = iter->flags & BOOTFLOWIF_SHOW; int method_flags; + char buf[32]; int ret; + if (label) { + const char *end = strchr(label, ':'); + + if (end) { + size_t len = (size_t)(end - label); + const char *part = end + 1; + + if (len + 1 > sizeof(buf)) { + log_err("label \"%s\" is way too long\n", label); + return -EINVAL; + } + + memcpy(buf, label, len); + buf[len] = '\0'; + label = buf; + + unsigned long tmp; + + if (strict_strtoul(part, 0, &tmp)) { + log_err("Invalid partition number: %s\n", part); + return -EINVAL; + } + + iter->flags |= BOOTFLOWIF_SINGLE_PARTITION; + iter->part = tmp; + } + } + ret = uclass_first_device_err(UCLASS_BOOTSTD, &bootstd); if (ret) { log_err("Missing bootstd device\n"); diff --git a/boot/bootflow.c b/boot/bootflow.c index 05484fd5b1b..68bf99329ab 100644 --- a/boot/bootflow.c +++ b/boot/bootflow.c @@ -217,6 +217,9 @@ static int iter_incr(struct bootflow_iter *iter) } } + if (iter->flags & BOOTFLOWIF_SINGLE_PARTITION) + return BF_NO_MORE_DEVICES; + /* No more bootmeths; start at the first one, and... */ iter->cur_method = 0; iter->method = iter->method_order[iter->cur_method]; diff --git a/doc/develop/bootstd.rst b/doc/develop/bootstd.rst index 496e24bc7a6..a07a72581e7 100644 --- a/doc/develop/bootstd.rst +++ b/doc/develop/bootstd.rst @@ -531,6 +531,10 @@ Then the iterator is set up to according to the parameters given: `BOOTFLOWIF_SINGLE_MEDIA` is set. In this case, moving to the next bootdev processes just the children of the media device. Hunters are used, in this example just the "mmc" hunter. + - If `label` indicates a particular partition in a particular media device + (e.g. "mmc1:3") then `BOOTFLOWIF_SINGLE_PARTITION` is set. In this case, + only a single partition within a bootdev is processed. Hunters are used, in + this example just the "mmc" hunter. - If `label` indicates a media uclass (e.g. "mmc") then `BOOTFLOWIF_SINGLE_UCLASS` is set. In this case, all bootdevs in that uclass are used. Hunters are used, in this example just the "mmc" hunter diff --git a/include/bootflow.h b/include/bootflow.h index 42112874f64..080ee850122 100644 --- a/include/bootflow.h +++ b/include/bootflow.h @@ -133,6 +133,8 @@ struct bootflow { * this uclass (used with things like "mmc") * @BOOTFLOWIF_SINGLE_MEDIA: (internal) Scan one media device in the uclass (used * with things like "mmc1") + * @BOOTFLOWIF_SINGLE_PARTITION: (internal) Scan one partition in media device + * (used with things like "mmc1:3") */ enum bootflow_iter_flags_t { BOOTFLOWIF_FIXED = 1 << 0, @@ -148,6 +150,7 @@ enum bootflow_iter_flags_t { BOOTFLOWIF_SKIP_GLOBAL = 1 << 17, BOOTFLOWIF_SINGLE_UCLASS = 1 << 18, BOOTFLOWIF_SINGLE_MEDIA = 1 << 19, + BOOTFLOWIF_SINGLE_PARTITION = 1 << 20, }; /** |