diff options
author | Furquan Shaikh <furquan@google.com> | 2015-06-02 10:32:52 -0700 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2015-06-04 11:57:47 +0000 |
commit | 7a1c0d1ec852ee86237aba7f3c87d642ca8e00b0 (patch) | |
tree | 191893fb52afa5fce615f6f1e2ff3929f8c349d6 | |
parent | 04e2338857e66ee1af7a826e320e6fe755711f65 (diff) | |
download | vboot-7a1c0d1ec852ee86237aba7f3c87d642ca8e00b0.tar.gz |
cgpt: Add a callback to allow override of GPT entry priority
This can be used by implementations that want to request vboot to
favor a particular kernel entry for booting without affecting the
checks for rollback protection and image verification.
CQ-DEPEND=CL:274716, CL:274932, CL:275171
BUG=None
BRANCH=None
TEST=Compiles successfully. make -j runtests successful.
Change-Id: I6a4600020354f5d4118c17f083c353c2585c4181
Signed-off-by: Furquan Shaikh <furquan@google.com>
Reviewed-on: https://chromium-review.googlesource.com/274558
Reviewed-by: Furquan Shaikh <furquan@chromium.org>
Reviewed-by: Stefan Reinauer <reinauer@chromium.org>
Tested-by: Nicolas Boichat <drinkcat@chromium.org>
Commit-Queue: Nicolas Boichat <drinkcat@chromium.org>
Trybot-Ready: Nicolas Boichat <drinkcat@chromium.org>
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | firmware/include/vboot_api.h | 14 | ||||
-rw-r--r-- | firmware/lib/cgptlib/cgptlib_internal.c | 6 | ||||
-rw-r--r-- | firmware/stub/vboot_api_stub.c | 5 | ||||
-rw-r--r-- | tests/cgptlib_test.c | 78 |
5 files changed, 105 insertions, 0 deletions
@@ -459,6 +459,7 @@ HOSTLIB_SRCS = \ firmware/lib/vboot_nvstorage.c \ firmware/stub/tpm_lite_stub.c \ firmware/stub/utility_stub.c \ + firmware/stub/vboot_api_stub.c \ firmware/stub/vboot_api_stub_disk.c \ firmware/stub/vboot_api_stub_init.c \ firmware/stub/vboot_api_stub_sf.c \ @@ -487,6 +488,7 @@ TINYHOSTLIB_SRCS = \ firmware/lib/cgptlib/crc32.c \ firmware/lib/gpt_misc.c \ firmware/lib/utility_string.c \ + firmware/stub/vboot_api_stub.c \ firmware/stub/vboot_api_stub_disk.c \ firmware/stub/vboot_api_stub_sf.c \ firmware/stub/utility_stub.c \ diff --git a/firmware/include/vboot_api.h b/firmware/include/vboot_api.h index 38f94033..53105407 100644 --- a/firmware/include/vboot_api.h +++ b/firmware/include/vboot_api.h @@ -24,6 +24,8 @@ #include <stdint.h> #include <stdlib.h> +#include "gpt.h" + /*****************************************************************************/ /* Error codes */ @@ -1057,4 +1059,16 @@ VbError_t VbUnlockDevice(void); */ VbError_t VbLockDevice(void); +/** + * Check if the firmware wants to override GPT entry priority. + * + * In case of kernel entry, check if there is an override of priority + * available. This is used to select a particular partition to boot in the + * current boot cycle. Rollback protection, image verification and all other + * checks in LoadKernel still remain the same. + * + * @param e Gpt Entry to check for priority override. + * @return 0 if no override, 1-15 for override priority. + */ +uint8_t VbExOverrideGptEntryPriority(const GptEntry *e); #endif /* VBOOT_REFERENCE_VBOOT_API_H_ */ diff --git a/firmware/lib/cgptlib/cgptlib_internal.c b/firmware/lib/cgptlib/cgptlib_internal.c index a389e695..29756308 100644 --- a/firmware/lib/cgptlib/cgptlib_internal.c +++ b/firmware/lib/cgptlib/cgptlib_internal.c @@ -370,6 +370,12 @@ int GetEntrySuccessful(const GptEntry *e) int GetEntryPriority(const GptEntry *e) { + int ret = VbExOverrideGptEntryPriority(e); + + /* Ensure that the override priority is valid. */ + if ((ret > 0) && (ret < 16)) + return ret; + return (e->attrs.fields.gpt_att & CGPT_ATTRIBUTE_PRIORITY_MASK) >> CGPT_ATTRIBUTE_PRIORITY_OFFSET; } diff --git a/firmware/stub/vboot_api_stub.c b/firmware/stub/vboot_api_stub.c index 6d82f121..7320b6ca 100644 --- a/firmware/stub/vboot_api_stub.c +++ b/firmware/stub/vboot_api_stub.c @@ -168,3 +168,8 @@ int VbExLegacy(void) { return 1; } + +uint8_t VbExOverrideGptEntryPriority(const GptEntry *e) +{ + return 0; +} diff --git a/tests/cgptlib_test.c b/tests/cgptlib_test.c index 13244a56..61747522 100644 --- a/tests/cgptlib_test.c +++ b/tests/cgptlib_test.c @@ -53,6 +53,18 @@ static const Guid guid_rootfs = GPT_ENT_TYPE_CHROMEOS_ROOTFS; const char *progname = "CGPT-TEST"; const char *command = "TEST"; +static int override_priority = 0; +static int override_counter = 0; + +uint8_t VbExOverrideGptEntryPriority(const GptEntry *e) +{ + if (override_counter == 0) + return override_priority; + + override_counter--; + return 0; +} + /* * Copy a random-for-this-program-only Guid into the dest. The num parameter * completely determines the Guid. @@ -1064,15 +1076,48 @@ static int EntryAttributeGetSetTest(void) EXPECT(0xFFF0FFFFFFFFFFFFULL == e->attrs.whole); EXPECT(0 == GetEntryPriority(e)); + e->attrs.whole = 0x0000000000000000ULL; + SetEntryPriority(e, 15); + override_priority = 10; + EXPECT(0x000F000000000000ULL == e->attrs.whole); + EXPECT(10 == GetEntryPriority(e)); + e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL; + SetEntryPriority(e, 0); + EXPECT(0xFFF0FFFFFFFFFFFFULL == e->attrs.whole); + EXPECT(10 == GetEntryPriority(e)); + override_priority = 0; + e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL; EXPECT(1 == GetEntrySuccessful(e)); EXPECT(15 == GetEntryPriority(e)); EXPECT(15 == GetEntryTries(e)); + override_priority = 10; + e->attrs.whole = 0xFFFFFFFFFFFFFFFFULL; + EXPECT(1 == GetEntrySuccessful(e)); + EXPECT(10 == GetEntryPriority(e)); + EXPECT(15 == GetEntryTries(e)); + override_priority = 0; + + e->attrs.whole = 0x0123000000000000ULL; + EXPECT(1 == GetEntrySuccessful(e)); + EXPECT(2 == GetEntryTries(e)); + EXPECT(3 == GetEntryPriority(e)); + + override_priority = 10; + e->attrs.whole = 0x0123000000000000ULL; + EXPECT(1 == GetEntrySuccessful(e)); + EXPECT(2 == GetEntryTries(e)); + EXPECT(10 == GetEntryPriority(e)); + override_priority = 0; + + /* Invalid priority */ + override_priority = 100; e->attrs.whole = 0x0123000000000000ULL; EXPECT(1 == GetEntrySuccessful(e)); EXPECT(2 == GetEntryTries(e)); EXPECT(3 == GetEntryPriority(e)); + override_priority = 0; return TEST_OK; } @@ -1307,6 +1352,38 @@ static int GptUpdateTest(void) return TEST_OK; } +static int GptOverridePriorityTest(void) +{ + GptData *gpt = GetEmptyGptData(); + GptEntry *e = (GptEntry *)(gpt->primary_entries); + uint64_t start, size; + + /* Tries=nonzero is attempted just like success, but tries=0 isn't */ + BuildTestGptData(gpt); + FillEntry(e + KERNEL_A, 1, 4, 1, 0); + FillEntry(e + KERNEL_B, 1, 3, 0, 2); + FillEntry(e + KERNEL_X, 1, 2, 0, 2); + RefreshCrc32(gpt); + GptInit(gpt); + gpt->modified = 0; /* Nothing modified yet */ + + override_counter = 1; + override_priority = 15; + + /* Kernel returned should be B instead of A */ + EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size)); + EXPECT(KERNEL_B == gpt->current_kernel); + + override_counter = 0; + override_priority = 0; + + /* Now, we should get A */ + EXPECT(GPT_SUCCESS == GptNextKernelEntry(gpt, &start, &size)); + EXPECT(KERNEL_A == gpt->current_kernel); + + return TEST_OK; +} + /* * Give an invalid kernel type, and expect GptUpdateKernelEntry() returns * GPT_ERROR_INVALID_UPDATE_TYPE. @@ -1514,6 +1591,7 @@ int main(int argc, char *argv[]) { TEST_CASE(GetNextPrioTest), }, { TEST_CASE(GetNextTriesTest), }, { TEST_CASE(GptUpdateTest), }, + { TEST_CASE(GptOverridePriorityTest), }, { TEST_CASE(UpdateInvalidKernelTypeTest), }, { TEST_CASE(DuplicateUniqueGuidTest), }, { TEST_CASE(TestCrc32TestVectors), }, |