At present all partitions are scanned, whether marked bootable or not.
Use only bootable partitions, defaulting to partition 1 if none is
found.

Signed-off-by: Simon Glass <s...@chromium.org>
---

(no changes since v1)

 boot/bootdev-uclass.c | 10 +++++++++-
 include/bootflow.h    |  2 ++
 test/boot/bootdev.c   | 37 +++++++++++++++++++++++++++++++++++++
 test/boot/bootflow.c  |  4 ++--
 4 files changed, 50 insertions(+), 3 deletions(-)

diff --git a/boot/bootdev-uclass.c b/boot/bootdev-uclass.c
index 081b94ce332..3dcf317c150 100644
--- a/boot/bootdev-uclass.c
+++ b/boot/bootdev-uclass.c
@@ -163,7 +163,15 @@ int bootdev_find_in_blk(struct udevice *dev, struct 
udevice *blk,
         */
        iter->max_part = MAX_PART_PER_BOOTDEV;
 
-       if (iter->part) {
+       /* If this is the whole disk, check if we have bootable partitions */
+       if (!iter->part) {
+               iter->first_bootable = part_get_bootable(desc);
+               log_debug("checking bootable=%d\n", iter->first_bootable);
+
+       /* if there are bootable partitions, scan only those */
+       } else if (iter->first_bootable ? !info.bootable : iter->part != 1) {
+               return log_msg_ret("boot", -EINVAL);
+       } else {
                ret = fs_set_blk_dev_with_part(desc, bflow->part);
                bflow->state = BOOTFLOWST_PART;
 
diff --git a/include/bootflow.h b/include/bootflow.h
index c201246c6de..3a93e4b5cab 100644
--- a/include/bootflow.h
+++ b/include/bootflow.h
@@ -123,6 +123,7 @@ enum bootflow_flags_t {
  * @method: Current bootmeth
  * @max_part: Maximum hardware partition number in @dev, 0 if there is no
  *     partition table
+ * @first_bootable: First bootable partition, or 0 if none
  * @err: Error obtained from checking the last iteration. This is used to skip
  *     forward (e.g. to skip the current partition because it is not valid)
  *     -ESHUTDOWN: try next bootdev
@@ -144,6 +145,7 @@ struct bootflow_iter {
        int part;
        struct udevice *method;
        int max_part;
+       int first_bootable;
        int err;
        int num_devs;
        int cur_dev;
diff --git a/test/boot/bootdev.c b/test/boot/bootdev.c
index 32a31c44609..db0e0ca20fa 100644
--- a/test/boot/bootdev.c
+++ b/test/boot/bootdev.c
@@ -301,3 +301,40 @@ static int bootdev_test_cmd_hunt(struct unit_test_state 
*uts)
 }
 BOOTSTD_TEST(bootdev_test_cmd_hunt, UT_TESTF_DM | UT_TESTF_SCAN_FDT |
             UT_TESTF_ETH_BOOTDEV);
+
+/* Check that only bootable partitions are processed */
+static int bootdev_test_bootable(struct unit_test_state *uts)
+{
+       struct bootflow_iter iter;
+       struct bootflow bflow;
+       struct udevice *blk;
+
+       memset(&iter, '\0', sizeof(iter));
+       memset(&bflow, '\0', sizeof(bflow));
+       iter.part = 0;
+       ut_assertok(uclass_get_device_by_name(UCLASS_BLK, "mmc1.blk", &blk));
+       iter.dev = blk;
+       ut_assertok(device_find_next_child(&iter.dev));
+       uclass_first_device(UCLASS_BOOTMETH, &bflow.method);
+
+       /*
+        * initially we don't have any knowledge of which partitions are
+        * bootable, but mmc1 has two partitions, with the first one being
+        * bootable
+        */
+       iter.part = 2;
+       ut_asserteq(-EINVAL, bootdev_find_in_blk(iter.dev, blk, &iter, &bflow));
+       ut_asserteq(0, iter.first_bootable);
+
+       /* scan with part == 0 to get the partition info */
+       iter.part = 0;
+       ut_asserteq(-ENOENT, bootdev_find_in_blk(iter.dev, blk, &iter, &bflow));
+       ut_asserteq(1, iter.first_bootable);
+
+       /* now it will refuse to use non-bootable partitions */
+       iter.part = 2;
+       ut_asserteq(-EINVAL, bootdev_find_in_blk(iter.dev, blk, &iter, &bflow));
+
+       return 0;
+}
+BOOTSTD_TEST(bootdev_test_bootable, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c
index 38ffe8fa9be..f852b6e9b6f 100644
--- a/test/boot/bootflow.c
+++ b/test/boot/bootflow.c
@@ -316,14 +316,14 @@ static int bootflow_iter(struct unit_test_state *uts)
        bootflow_free(&bflow);
 
        /* Then more to partition 2 which exists but is not bootable */
-       ut_asserteq(-EPERM, bootflow_scan_next(&iter, &bflow));
+       ut_asserteq(-EINVAL, bootflow_scan_next(&iter, &bflow));
        ut_asserteq(2, iter.num_methods);
        ut_asserteq(0, iter.cur_method);
        ut_asserteq(2, iter.part);
        ut_asserteq(0x1e, iter.max_part);
        ut_asserteq_str("syslinux", iter.method->name);
        ut_asserteq(0, bflow.err);
-       ut_asserteq(BOOTFLOWST_PART, bflow.state);
+       ut_asserteq(BOOTFLOWST_MEDIA, bflow.state);
        bootflow_free(&bflow);
 
        bootflow_iter_uninit(&iter);
-- 
2.39.0.246.g2a6d74b583-goog

Reply via email to