From f0e358f07d75579b40eff8f723b280ab5d53d338 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 17 Jan 2023 10:47:42 -0700 Subject: [PATCH] bootstd: Only scan bootable partitions 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 --- 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 081b94c..3dcf317 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 c201246..3a93e4b 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 32a31c4..db0e0ca 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 38ffe8f..f852b6e 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.7.4