aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--boot/bootdev-uclass.c35
-rw-r--r--boot/bootflow.c3
-rw-r--r--doc/develop/bootstd.rst4
-rw-r--r--include/bootflow.h3
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,
};
/**