From 2d1ce45dc46b0dd5522edf1edabef35b90a66942 Mon Sep 17 00:00:00 2001 From: Yu-Ping Wu Date: Wed, 13 Oct 2021 11:02:20 +0800 Subject: vboot: Support booting from non-active miniOS partition To support booting from the non-active miniOS partition in recovery UI, add minios_flags argument to VbTryLoadMiniOsKernel. Currently there is only one flag: VB_MINIOS_FLAG_NON_ACTIVE. When it is set, we will attempt to boot from the non-active partition only. BUG=b:200750322 TEST=make runtests BRANCH=none Cq-Depend: chromium:3219727 Change-Id: I6221f10c09de2487e89e6113981bc9e9755d67f4 Signed-off-by: Yu-Ping Wu Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/3219901 Reviewed-by: Julius Werner Reviewed-by: Jae Hoon Kim --- firmware/include/vboot_api.h | 9 +++++- firmware/lib/include/load_kernel_fw.h | 3 +- firmware/lib/vboot_api_kernel.c | 12 ++++--- firmware/lib/vboot_kernel.c | 9 ++++-- tests/vboot_api_kernel_tests.c | 4 +-- tests/vboot_kernel2_tests.c | 59 ++++++++++++++++++++++++----------- 6 files changed, 66 insertions(+), 30 deletions(-) diff --git a/firmware/include/vboot_api.h b/firmware/include/vboot_api.h index f19ee747..1fee766d 100644 --- a/firmware/include/vboot_api.h +++ b/firmware/include/vboot_api.h @@ -89,6 +89,11 @@ vb2_error_t VbSelectAndLoadKernel(struct vb2_context *ctx, */ vb2_error_t VbTryLoadKernel(struct vb2_context *ctx, uint32_t disk_flags); +/* miniOS flags */ + +/* Boot from non-active miniOS partition only */ +#define VB_MINIOS_FLAG_NON_ACTIVE (1 << 0) + /** * Attempt loading a miniOS kernel from internal disk. * @@ -100,9 +105,11 @@ vb2_error_t VbTryLoadKernel(struct vb2_context *ctx, uint32_t disk_flags); * VB2_SUCCESS. * * @param ctx Vboot context + * @param minios_flags Flags for miniOS * @return VB2_SUCCESS or the most specific VB2_ERROR_LK error. */ -vb2_error_t VbTryLoadMiniOsKernel(struct vb2_context *ctx); +vb2_error_t VbTryLoadMiniOsKernel(struct vb2_context *ctx, + uint32_t minios_flags); /*****************************************************************************/ /* Disk access (previously in boot_device.h) */ diff --git a/firmware/lib/include/load_kernel_fw.h b/firmware/lib/include/load_kernel_fw.h index af454703..76d25560 100644 --- a/firmware/lib/include/load_kernel_fw.h +++ b/firmware/lib/include/load_kernel_fw.h @@ -30,11 +30,12 @@ vb2_error_t LoadKernel(struct vb2_context *ctx, * @param ctx Vboot context * @param params Params specific to loading the kernel * @param disk_info Disk from which to read kernel + * @param minios_flags Flags for miniOS * * Returns VB2_SUCCESS if successful. If unsuccessful, returns an error code. */ vb2_error_t LoadMiniOsKernel(struct vb2_context *ctx, VbSelectAndLoadKernelParams *params, - VbDiskInfo *disk_info); + VbDiskInfo *disk_info, uint32_t minios_flags); #endif /* VBOOT_REFERENCE_LOAD_KERNEL_FW_H_ */ diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c index 2abd57eb..54447c26 100644 --- a/firmware/lib/vboot_api_kernel.c +++ b/firmware/lib/vboot_api_kernel.c @@ -62,7 +62,8 @@ static int is_valid_disk(VbDiskInfo *info, uint32_t disk_flags) } static vb2_error_t VbTryLoadKernelImpl(struct vb2_context *ctx, - uint32_t disk_flags, int minios) + uint32_t disk_flags, int minios, + uint32_t minios_flags) { vb2_error_t rv = VB2_ERROR_LK_NO_DISK_FOUND; VbDiskInfo* disk_info = NULL; @@ -96,7 +97,7 @@ static vb2_error_t VbTryLoadKernelImpl(struct vb2_context *ctx, if (minios) { new_rv = LoadMiniOsKernel(ctx, kparams_ptr, - &disk_info[i]); + &disk_info[i], minios_flags); VB2_DEBUG("LoadMiniOsKernel() = %#x\n", new_rv); } else { new_rv = LoadKernel(ctx, kparams_ptr, &disk_info[i]); @@ -142,13 +143,14 @@ static vb2_error_t VbTryLoadKernelImpl(struct vb2_context *ctx, test_mockable vb2_error_t VbTryLoadKernel(struct vb2_context *ctx, uint32_t disk_flags) { - return VbTryLoadKernelImpl(ctx, disk_flags, 0); + return VbTryLoadKernelImpl(ctx, disk_flags, 0, 0); } test_mockable -vb2_error_t VbTryLoadMiniOsKernel(struct vb2_context *ctx) +vb2_error_t VbTryLoadMiniOsKernel(struct vb2_context *ctx, + uint32_t minios_flags) { - return VbTryLoadKernelImpl(ctx, VB_DISK_FLAG_FIXED, 1); + return VbTryLoadKernelImpl(ctx, VB_DISK_FLAG_FIXED, 1, minios_flags); } vb2_error_t VbSelectAndLoadKernel(struct vb2_context *ctx, diff --git a/firmware/lib/vboot_kernel.c b/firmware/lib/vboot_kernel.c index 34a8a426..cb83d40d 100644 --- a/firmware/lib/vboot_kernel.c +++ b/firmware/lib/vboot_kernel.c @@ -607,12 +607,17 @@ static vb2_error_t try_minios_sector_region(struct vb2_context *ctx, */ vb2_error_t LoadMiniOsKernel(struct vb2_context *ctx, VbSelectAndLoadKernelParams *params, - VbDiskInfo *disk_info) + VbDiskInfo *disk_info, uint32_t minios_flags) { vb2_error_t rv; int end_region_first = vb2_nv_get(ctx, VB2_NV_MINIOS_PRIORITY); - rv = try_minios_sector_region(ctx, params, disk_info, end_region_first); + if (minios_flags & VB_MINIOS_FLAG_NON_ACTIVE) + rv = VB2_ERROR_UNKNOWN; /* Ignore active partition */ + else + rv = try_minios_sector_region(ctx, params, disk_info, + end_region_first); + if (rv) rv = try_minios_sector_region(ctx, params, disk_info, !end_region_first); diff --git a/tests/vboot_api_kernel_tests.c b/tests/vboot_api_kernel_tests.c index 51f0ddb1..b66c4320 100644 --- a/tests/vboot_api_kernel_tests.c +++ b/tests/vboot_api_kernel_tests.c @@ -563,7 +563,7 @@ vb2_error_t LoadKernel(struct vb2_context *c, vb2_error_t LoadMiniOsKernel(struct vb2_context *c, VbSelectAndLoadKernelParams *params, - VbDiskInfo *disk_info) + VbDiskInfo *disk_info, uint32_t minios_flags) { lk_minios_calls++; return LoadKernelImpl(c, params, disk_info); @@ -616,7 +616,7 @@ static void VbTryLoadMiniOsKernelTest(void) printf("Test case: %s ...\n", minios_tests[i].name); ResetMocks(&minios_tests[i]); ctx->flags = t->ctx_flags; - TEST_EQ(VbTryLoadMiniOsKernel(ctx), + TEST_EQ(VbTryLoadMiniOsKernel(ctx, 0), t->expected_return_val, " return value"); TEST_EQ(got_recovery_request_val, t->expected_recovery_request_val, " recovery_request"); diff --git a/tests/vboot_kernel2_tests.c b/tests/vboot_kernel2_tests.c index 5424e86c..bc4ea0fe 100644 --- a/tests/vboot_kernel2_tests.c +++ b/tests/vboot_kernel2_tests.c @@ -264,7 +264,7 @@ static void load_minios_kernel_tests(void) disk_info.bytes_per_lba = KBUF_SIZE; disk_info.lba_count = 1; add_mock_kernel(0, VB2_SUCCESS); - TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info), + TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), "{valid kernel}"); TEST_EQ(mock_tpm_set_mode_calls, 1, " TPM disabled"); @@ -272,7 +272,7 @@ static void load_minios_kernel_tests(void) reset_common_data(); disk_info.bytes_per_lba = KBUF_SIZE; disk_info.lba_count = 1; - TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info), + TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), VB2_ERROR_LK_NO_KERNEL_FOUND, "{no kernel}"); TEST_EQ(mock_tpm_set_mode_calls, 0, " TPM not disabled"); @@ -281,7 +281,7 @@ static void load_minios_kernel_tests(void) disk_info.bytes_per_lba = KBUF_SIZE; disk_info.lba_count = 2; add_mock_kernel(1, VB2_SUCCESS); - TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info), + TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), "{no kernel, valid kernel}"); TEST_EQ(cur_kernel->sector, 1, " select kernel"); @@ -290,7 +290,7 @@ static void load_minios_kernel_tests(void) disk_info.lba_count = 2; add_mock_kernel(0, VB2_ERROR_MOCK); add_mock_kernel(1, VB2_SUCCESS); - TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info), + TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), "{invalid kernel, valid kernel}"); TEST_EQ(cur_kernel->sector, 1, " select second kernel"); @@ -299,7 +299,7 @@ static void load_minios_kernel_tests(void) disk_info.lba_count = 2; add_mock_kernel(0, VB2_ERROR_MOCK); add_mock_kernel(1, VB2_ERROR_MOCK); - TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info), + TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), VB2_ERROR_LK_NO_KERNEL_FOUND, "{invalid kernel, invalid kernel}"); TEST_EQ(mock_tpm_set_mode_calls, 0, @@ -310,7 +310,7 @@ static void load_minios_kernel_tests(void) disk_info.lba_count = 2; add_mock_kernel(0, VB2_SUCCESS); add_mock_kernel(1, VB2_SUCCESS); - TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info), + TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), "{valid kernel, valid kernel} minios_priority=0"); TEST_EQ(cur_kernel->sector, 0, " select first kernel"); @@ -320,15 +320,36 @@ static void load_minios_kernel_tests(void) add_mock_kernel(0, VB2_SUCCESS); add_mock_kernel(1, VB2_SUCCESS); vb2_nv_set(ctx, VB2_NV_MINIOS_PRIORITY, 1); - TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info), + TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), "{valid kernel, valid kernel} minios_priority=1"); TEST_EQ(cur_kernel->sector, 1, " select second kernel"); + reset_common_data(); + disk_info.bytes_per_lba = KBUF_SIZE; + disk_info.lba_count = 2; + add_mock_kernel(0, VB2_SUCCESS); + add_mock_kernel(1, VB2_SUCCESS); + TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, + VB_MINIOS_FLAG_NON_ACTIVE), + "{valid kernel, valid kernel} minios_priority=0 non-active"); + TEST_EQ(cur_kernel->sector, 1, " select second kernel"); + + reset_common_data(); + disk_info.bytes_per_lba = KBUF_SIZE; + disk_info.lba_count = 2; + add_mock_kernel(0, VB2_ERROR_MOCK); + add_mock_kernel(1, VB2_SUCCESS); + vb2_nv_set(ctx, VB2_NV_MINIOS_PRIORITY, 1); + TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info, + VB_MINIOS_FLAG_NON_ACTIVE), + VB2_ERROR_LK_NO_KERNEL_FOUND, + "{invalid kernel, valid kernel} minios_priority=1 non-active"); + reset_common_data(); disk_info.bytes_per_lba = VB2_KEYBLOCK_MAGIC_SIZE; disk_info.lba_count = 4; add_mock_kernel(1, VB2_SUCCESS); - TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info), + TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), VB2_ERROR_LK_NO_KERNEL_FOUND, "valid kernel header near start of disk (disk too small)"); @@ -336,7 +357,7 @@ static void load_minios_kernel_tests(void) disk_info.bytes_per_lba = VB2_KEYBLOCK_MAGIC_SIZE; disk_info.lba_count = 1000; add_mock_kernel(999, VB2_SUCCESS); - TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info), + TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), VB2_ERROR_LK_NO_KERNEL_FOUND, "valid kernel header near end of disk"); @@ -344,35 +365,35 @@ static void load_minios_kernel_tests(void) disk_info.bytes_per_lba = 1024; disk_info.lba_count = 128; add_mock_kernel(63, VB2_SUCCESS); - TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info), + TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), "start/end overlap assuming >128 MB search range (start)"); reset_common_data(); disk_info.bytes_per_lba = 1024; disk_info.lba_count = 128; add_mock_kernel(64, VB2_SUCCESS); - TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info), + TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), "start/end overlap assuming >128 MB search range (end)"); reset_common_data(); disk_info.bytes_per_lba = 128; disk_info.lba_count = 1024; add_mock_kernel(3, VB2_SUCCESS); - TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info), + TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), "kernel at last sector in batch assuming 512 KB batches"); reset_common_data(); disk_info.bytes_per_lba = 256; disk_info.lba_count = 1024; add_mock_kernel(3, VB2_SUCCESS); - TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info), + TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), "kernel at last sector in batch assuming 1 MB batches"); reset_common_data(); disk_info.bytes_per_lba = 512; disk_info.lba_count = 1024; add_mock_kernel(3, VB2_SUCCESS); - TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info), + TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), "kernel at last sector in batch assuming 2 MB batches"); reset_common_data(); @@ -382,7 +403,7 @@ static void load_minios_kernel_tests(void) disk_info.bytes_per_lba = KBUF_SIZE; disk_info.lba_count = 2; add_mock_kernel(0, VB2_SUCCESS); - TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info), + TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), "kernel with minios keyblock flag"); reset_common_data(); @@ -392,7 +413,7 @@ static void load_minios_kernel_tests(void) disk_info.bytes_per_lba = KBUF_SIZE; disk_info.lba_count = 2; add_mock_kernel(0, VB2_SUCCESS); - TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info), + TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), VB2_ERROR_LK_NO_KERNEL_FOUND, "kernel with !minios keyblock flag"); @@ -402,7 +423,7 @@ static void load_minios_kernel_tests(void) add_mock_kernel(0, VB2_SUCCESS); sd->kernel_version_secdata = 5 << 24; kph.kernel_version = 4; - TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info), + TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), VB2_ERROR_LK_NO_KERNEL_FOUND, "kernel version too old"); @@ -412,7 +433,7 @@ static void load_minios_kernel_tests(void) add_mock_kernel(0, VB2_SUCCESS); sd->kernel_version_secdata = 5 << 24; kph.kernel_version = 0x100; - TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info), + TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), VB2_ERROR_LK_NO_KERNEL_FOUND, "kernel version greater than 0xff"); @@ -422,7 +443,7 @@ static void load_minios_kernel_tests(void) add_mock_kernel(0, VB2_SUCCESS); sd->kernel_version_secdata = 5 << 24; kph.kernel_version = 6; - TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info), + TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), "newer kernel version"); } -- cgit v1.2.1