123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576 |
- /* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- * Tests for misc library
- */
- #include "2sysincludes.h"
- #include "2api.h"
- #include "2common.h"
- #include "2misc.h"
- #include "2nvstorage.h"
- #include "2secdata.h"
- #include "test_common.h"
- /* Common context for tests */
- static uint8_t workbuf[VB2_WORKBUF_RECOMMENDED_SIZE]
- __attribute__ ((aligned (VB2_WORKBUF_ALIGN)));
- static struct vb2_context cc;
- static struct vb2_shared_data *sd;
- /* Mocked function data */
- enum vb2_resource_index mock_resource_index;
- void *mock_resource_ptr;
- uint32_t mock_resource_size;
- int mock_tpm_clear_called;
- int mock_tpm_clear_retval;
- static void reset_common_data(void)
- {
- memset(workbuf, 0xaa, sizeof(workbuf));
- memset(&cc, 0, sizeof(cc));
- cc.workbuf = workbuf;
- cc.workbuf_size = sizeof(workbuf);
- vb2_init_context(&cc);
- sd = vb2_get_sd(&cc);
- vb2_nv_init(&cc);
- vb2_secdata_create(&cc);
- vb2_secdata_init(&cc);
- mock_tpm_clear_called = 0;
- mock_tpm_clear_retval = VB2_SUCCESS;
- };
- /* Mocked functions */
- int vb2ex_read_resource(struct vb2_context *ctx,
- enum vb2_resource_index index,
- uint32_t offset,
- void *buf,
- uint32_t size)
- {
- if (index != mock_resource_index)
- return VB2_ERROR_EX_READ_RESOURCE_INDEX;
- if (offset > mock_resource_size || offset + size > mock_resource_size)
- return VB2_ERROR_EX_READ_RESOURCE_SIZE;
- memcpy(buf, (uint8_t *)mock_resource_ptr + offset, size);
- return VB2_SUCCESS;
- }
- int vb2ex_tpm_clear_owner(struct vb2_context *ctx)
- {
- mock_tpm_clear_called++;
- return mock_tpm_clear_retval;
- }
- /* Tests */
- static void init_context_tests(void)
- {
- /* Use our own context struct so we can re-init it */
- struct vb2_context c = {
- .workbuf = workbuf,
- .workbuf_size = sizeof(workbuf),
- };
- reset_common_data();
- TEST_SUCC(vb2_init_context(&c), "Init context good");
- TEST_EQ(c.workbuf_used, sizeof(struct vb2_shared_data),
- "Init vbsd");
- /* Don't re-init if used is non-zero */
- c.workbuf_used = 200;
- TEST_SUCC(vb2_init_context(&c), "Re-init context good");
- TEST_EQ(c.workbuf_used, 200, "Didn't re-init");
- /* Handle workbuf errors */
- c.workbuf_used = 0;
- c.workbuf_size = sizeof(struct vb2_shared_data) - 1;
- TEST_EQ(vb2_init_context(&c),
- VB2_ERROR_INITCTX_WORKBUF_SMALL, "Init too small");
- c.workbuf_size = sizeof(workbuf);
- /* Handle workbuf unaligned */
- c.workbuf++;
- TEST_EQ(vb2_init_context(&c),
- VB2_ERROR_INITCTX_WORKBUF_ALIGN, "Init unaligned");
- }
- static void misc_tests(void)
- {
- struct vb2_workbuf wb;
- reset_common_data();
- cc.workbuf_used = 16;
- vb2_workbuf_from_ctx(&cc, &wb);
- TEST_PTR_EQ(wb.buf, workbuf + 16, "vb_workbuf_from_ctx() buf");
- TEST_EQ(wb.size, cc.workbuf_size - 16, "vb_workbuf_from_ctx() size");
- }
- static void gbb_tests(void)
- {
- struct vb2_gbb_header gbb = {
- .signature = {'$', 'G', 'B', 'B'},
- .major_version = VB2_GBB_MAJOR_VER,
- .minor_version = VB2_GBB_MINOR_VER,
- .header_size = sizeof(struct vb2_gbb_header),
- .flags = 0x1234,
- .rootkey_offset = 240,
- .rootkey_size = 1040,
- };
- struct vb2_gbb_header gbbdest;
- TEST_EQ(sizeof(struct vb2_gbb_header),
- EXPECTED_VB2_GBB_HEADER_SIZE,
- "sizeof(struct vb2_gbb_header)");
- reset_common_data();
- /* Good contents */
- mock_resource_index = VB2_RES_GBB;
- mock_resource_ptr = &gbb;
- mock_resource_size = sizeof(gbb);
- TEST_SUCC(vb2_read_gbb_header(&cc, &gbbdest), "read gbb header good");
- TEST_SUCC(memcmp(&gbb, &gbbdest, sizeof(gbb)), "read gbb contents");
- mock_resource_index = VB2_RES_GBB + 1;
- TEST_EQ(vb2_read_gbb_header(&cc, &gbbdest),
- VB2_ERROR_EX_READ_RESOURCE_INDEX, "read gbb header missing");
- mock_resource_index = VB2_RES_GBB;
- gbb.signature[0]++;
- TEST_EQ(vb2_read_gbb_header(&cc, &gbbdest),
- VB2_ERROR_GBB_MAGIC, "read gbb header bad magic");
- gbb.signature[0]--;
- gbb.major_version = VB2_GBB_MAJOR_VER + 1;
- TEST_EQ(vb2_read_gbb_header(&cc, &gbbdest),
- VB2_ERROR_GBB_VERSION, "read gbb header major version");
- gbb.major_version = VB2_GBB_MAJOR_VER;
- gbb.minor_version = VB2_GBB_MINOR_VER + 1;
- TEST_SUCC(vb2_read_gbb_header(&cc, &gbbdest),
- "read gbb header minor++");
- gbb.minor_version = 1;
- TEST_EQ(vb2_read_gbb_header(&cc, &gbbdest),
- VB2_ERROR_GBB_TOO_OLD, "read gbb header 1.1 fails");
- gbb.minor_version = 0;
- TEST_EQ(vb2_read_gbb_header(&cc, &gbbdest),
- VB2_ERROR_GBB_TOO_OLD, "read gbb header 1.0 fails");
- gbb.minor_version = VB2_GBB_MINOR_VER;
- gbb.header_size--;
- TEST_EQ(vb2_read_gbb_header(&cc, &gbbdest),
- VB2_ERROR_GBB_HEADER_SIZE, "read gbb header size");
- TEST_EQ(vb2_fw_parse_gbb(&cc),
- VB2_ERROR_GBB_HEADER_SIZE, "parse gbb failure");
- gbb.header_size++;
- /* Parse GBB */
- TEST_SUCC(vb2_fw_parse_gbb(&cc), "parse gbb");
- TEST_EQ(sd->gbb_flags, gbb.flags, "gbb flags");
- TEST_EQ(sd->gbb_rootkey_offset, gbb.rootkey_offset, "rootkey offset");
- TEST_EQ(sd->gbb_rootkey_size, gbb.rootkey_size, "rootkey size");
- /* Workbuf failure */
- reset_common_data();
- cc.workbuf_used = cc.workbuf_size - 4;
- TEST_EQ(vb2_fw_parse_gbb(&cc),
- VB2_ERROR_GBB_WORKBUF, "parse gbb no workbuf");
- }
- static void fail_tests(void)
- {
- /* Early fail (before even NV init) */
- reset_common_data();
- sd->status &= ~VB2_SD_STATUS_NV_INIT;
- vb2_fail(&cc, 1, 2);
- TEST_NEQ(sd->status & VB2_SD_STATUS_NV_INIT, 0, "vb2_fail inits NV");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_REQUEST),
- 1, "vb2_fail request");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_SUBCODE),
- 2, "vb2_fail subcode");
- /* Repeated fail doesn't overwrite the error code */
- vb2_fail(&cc, 3, 4);
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_REQUEST),
- 1, "vb2_fail repeat");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_SUBCODE),
- 2, "vb2_fail repeat2");
- /* Fail with other slot good doesn't trigger recovery */
- reset_common_data();
- vb2_nv_set(&cc, VB2_NV_TRY_COUNT, 3);
- vb2_nv_set(&cc, VB2_NV_FW_RESULT, VB2_FW_RESULT_UNKNOWN);
- sd->status |= VB2_SD_STATUS_CHOSE_SLOT;
- sd->fw_slot = 0;
- sd->last_fw_slot = 1;
- sd->last_fw_result = VB2_FW_RESULT_UNKNOWN;
- vb2_fail(&cc, 5, 6);
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_REQUEST), 0, "vb2_failover");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_RESULT),
- VB2_FW_RESULT_FAILURE, "vb2_fail this fw");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_TRY_COUNT), 0, "vb2_fail use up tries");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_TRY_NEXT), 1, "vb2_fail try other slot");
- /* Fail with other slot already failing triggers recovery */
- reset_common_data();
- sd->status |= VB2_SD_STATUS_CHOSE_SLOT;
- sd->fw_slot = 1;
- sd->last_fw_slot = 0;
- sd->last_fw_result = VB2_FW_RESULT_FAILURE;
- vb2_fail(&cc, 7, 8);
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_REQUEST), 7,
- "vb2_fail both slots bad");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_RESULT),
- VB2_FW_RESULT_FAILURE, "vb2_fail this fw");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_TRY_NEXT), 0, "vb2_fail try other slot");
- }
- static void recovery_tests(void)
- {
- /* No recovery */
- reset_common_data();
- vb2_check_recovery(&cc);
- TEST_EQ(sd->recovery_reason, 0, "No recovery reason");
- TEST_EQ(sd->flags & VB2_SD_FLAG_MANUAL_RECOVERY,
- 0, "Not manual recovery");
- TEST_EQ(cc.flags & VB2_CONTEXT_RECOVERY_MODE,
- 0, "Not recovery mode");
- /* From request */
- reset_common_data();
- vb2_nv_set(&cc, VB2_NV_RECOVERY_REQUEST, 3);
- vb2_check_recovery(&cc);
- TEST_EQ(sd->recovery_reason, 3, "Recovery reason from request");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_REQUEST), 0, "NV cleared");
- TEST_EQ(sd->flags & VB2_SD_FLAG_MANUAL_RECOVERY,
- 0, "Not manual recovery");
- TEST_NEQ(cc.flags & VB2_CONTEXT_RECOVERY_MODE,
- 0, "Recovery mode");
- /* From request, but already failed */
- reset_common_data();
- vb2_nv_set(&cc, VB2_NV_RECOVERY_REQUEST, 4);
- sd->recovery_reason = 5;
- vb2_check_recovery(&cc);
- TEST_EQ(sd->recovery_reason, 5, "Recovery reason already failed");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_REQUEST),
- 0, "NV still cleared");
- /* Override */
- reset_common_data();
- sd->recovery_reason = 6;
- cc.flags |= VB2_CONTEXT_FORCE_RECOVERY_MODE;
- vb2_check_recovery(&cc);
- TEST_EQ(sd->recovery_reason, VB2_RECOVERY_RO_MANUAL,
- "Recovery reason forced");
- TEST_NEQ(sd->flags & VB2_SD_FLAG_MANUAL_RECOVERY,
- 0, "SD flag set");
- }
- static void dev_switch_tests(void)
- {
- uint32_t v;
- /* Normal mode */
- reset_common_data();
- TEST_SUCC(vb2_check_dev_switch(&cc), "dev mode off");
- TEST_EQ(sd->flags & VB2_SD_DEV_MODE_ENABLED, 0, " sd not in dev");
- TEST_EQ(cc.flags & VB2_CONTEXT_DEVELOPER_MODE, 0, " ctx not in dev");
- TEST_EQ(mock_tpm_clear_called, 0, " no tpm clear");
- /* Dev mode */
- reset_common_data();
- vb2_secdata_set(&cc, VB2_SECDATA_FLAGS,
- (VB2_SECDATA_FLAG_DEV_MODE |
- VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER));
- TEST_SUCC(vb2_check_dev_switch(&cc), "dev mode on");
- TEST_NEQ(sd->flags & VB2_SD_DEV_MODE_ENABLED, 0, " sd in dev");
- TEST_NEQ(cc.flags & VB2_CONTEXT_DEVELOPER_MODE, 0, " ctx in dev");
- TEST_EQ(mock_tpm_clear_called, 0, " no tpm clear");
- /* Any normal mode boot clears dev boot flags */
- reset_common_data();
- vb2_nv_set(&cc, VB2_NV_DEV_BOOT_USB, 1);
- vb2_nv_set(&cc, VB2_NV_DEV_BOOT_LEGACY, 1);
- vb2_nv_set(&cc, VB2_NV_DEV_BOOT_SIGNED_ONLY, 1);
- vb2_nv_set(&cc, VB2_NV_DEV_BOOT_FASTBOOT_FULL_CAP, 1);
- vb2_nv_set(&cc, VB2_NV_DEV_DEFAULT_BOOT, 1);
- vb2_nv_set(&cc, VB2_NV_FASTBOOT_UNLOCK_IN_FW, 1);
- TEST_SUCC(vb2_check_dev_switch(&cc), "dev mode off");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_DEV_BOOT_USB),
- 0, " cleared dev boot usb");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_DEV_BOOT_LEGACY),
- 0, " cleared dev boot legacy");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_DEV_BOOT_SIGNED_ONLY),
- 0, " cleared dev boot signed only");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_DEV_BOOT_FASTBOOT_FULL_CAP),
- 0, " cleared dev boot fastboot full cap");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_DEV_DEFAULT_BOOT),
- 0, " cleared dev default boot");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_FASTBOOT_UNLOCK_IN_FW),
- 0, " cleared dev boot fastboot unlock in fw");
- /* Normal-dev transition clears TPM */
- reset_common_data();
- vb2_secdata_set(&cc, VB2_SECDATA_FLAGS, VB2_SECDATA_FLAG_DEV_MODE);
- TEST_SUCC(vb2_check_dev_switch(&cc), "to dev mode");
- TEST_EQ(mock_tpm_clear_called, 1, " tpm clear");
- vb2_secdata_get(&cc, VB2_SECDATA_FLAGS, &v);
- TEST_EQ(v, (VB2_SECDATA_FLAG_DEV_MODE |
- VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER),
- " last boot developer now");
- /* Dev-normal transition clears TPM too */
- reset_common_data();
- vb2_secdata_set(&cc, VB2_SECDATA_FLAGS,
- VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER);
- TEST_SUCC(vb2_check_dev_switch(&cc), "from dev mode");
- TEST_EQ(mock_tpm_clear_called, 1, " tpm clear");
- vb2_secdata_get(&cc, VB2_SECDATA_FLAGS, &v);
- TEST_EQ(v, 0, " last boot not developer now");
- /* Disable dev mode */
- reset_common_data();
- vb2_secdata_set(&cc, VB2_SECDATA_FLAGS,
- (VB2_SECDATA_FLAG_DEV_MODE |
- VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER));
- vb2_nv_set(&cc, VB2_NV_DISABLE_DEV_REQUEST, 1);
- TEST_SUCC(vb2_check_dev_switch(&cc), "disable dev request");
- TEST_EQ(sd->flags & VB2_SD_DEV_MODE_ENABLED, 0, " sd not in dev");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_DISABLE_DEV_REQUEST),
- 0, " request cleared");
- /* Force enabled by GBB */
- reset_common_data();
- sd->gbb_flags |= VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON;
- TEST_SUCC(vb2_check_dev_switch(&cc), "dev on via gbb");
- TEST_NEQ(sd->flags & VB2_SD_DEV_MODE_ENABLED, 0, " sd in dev");
- vb2_secdata_get(&cc, VB2_SECDATA_FLAGS, &v);
- TEST_EQ(v, VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER,
- " doesn't set dev on in secdata but does set last boot dev");
- TEST_EQ(mock_tpm_clear_called, 1, " tpm clear");
- /* Force enabled by ctx flag */
- reset_common_data();
- cc.flags |= VB2_CONTEXT_FORCE_DEVELOPER_MODE;
- TEST_SUCC(vb2_check_dev_switch(&cc), "dev on via ctx flag");
- TEST_NEQ(sd->flags & VB2_SD_DEV_MODE_ENABLED, 0, " sd in dev");
- vb2_secdata_get(&cc, VB2_SECDATA_FLAGS, &v);
- TEST_EQ(v, VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER,
- " doesn't set dev on in secdata but does set last boot dev");
- TEST_EQ(mock_tpm_clear_called, 1, " tpm clear");
- /* Simulate clear owner failure */
- reset_common_data();
- vb2_secdata_set(&cc, VB2_SECDATA_FLAGS,
- VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER);
- mock_tpm_clear_retval = VB2_ERROR_EX_TPM_CLEAR_OWNER;
- TEST_EQ(vb2_check_dev_switch(&cc),
- VB2_ERROR_EX_TPM_CLEAR_OWNER, "tpm clear fail");
- TEST_EQ(mock_tpm_clear_called, 1, " tpm clear");
- vb2_secdata_get(&cc, VB2_SECDATA_FLAGS, &v);
- TEST_EQ(v, VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER,
- " last boot still developer");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_REQUEST),
- VB2_RECOVERY_TPM_CLEAR_OWNER, " requests recovery");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_SUBCODE),
- (uint8_t)VB2_ERROR_EX_TPM_CLEAR_OWNER, " recovery subcode");
- /*
- * Secdata failure in normal mode fails and shows dev=0 even if dev
- * mode was on in the (inaccessible) secdata.
- */
- reset_common_data();
- vb2_secdata_set(&cc, VB2_SECDATA_FLAGS, VB2_SECDATA_FLAG_DEV_MODE);
- sd->status &= ~VB2_SD_STATUS_SECDATA_INIT;
- TEST_EQ(vb2_check_dev_switch(&cc), VB2_ERROR_SECDATA_GET_UNINITIALIZED,
- "secdata fail normal");
- TEST_EQ(sd->flags & VB2_SD_DEV_MODE_ENABLED, 0, " sd not in dev");
- TEST_EQ(cc.flags & VB2_CONTEXT_DEVELOPER_MODE, 0, " ctx not in dev");
- /* Secdata failure in recovery mode continues */
- reset_common_data();
- cc.flags |= VB2_CONTEXT_RECOVERY_MODE;
- sd->status &= ~VB2_SD_STATUS_SECDATA_INIT;
- TEST_SUCC(vb2_check_dev_switch(&cc), "secdata fail recovery");
- TEST_EQ(sd->flags & VB2_SD_DEV_MODE_ENABLED, 0, " sd not in dev");
- TEST_EQ(cc.flags & VB2_CONTEXT_DEVELOPER_MODE, 0, " ctx not in dev");
- /* And doesn't check or clear dev disable request */
- reset_common_data();
- cc.flags |= VB2_CONTEXT_RECOVERY_MODE;
- sd->status &= ~VB2_SD_STATUS_SECDATA_INIT;
- vb2_nv_set(&cc, VB2_NV_DISABLE_DEV_REQUEST, 1);
- TEST_SUCC(vb2_check_dev_switch(&cc), "secdata fail recovery disable");
- TEST_EQ(sd->flags & VB2_SD_DEV_MODE_ENABLED, 0, " sd not in dev");
- TEST_EQ(cc.flags & VB2_CONTEXT_DEVELOPER_MODE, 0, " ctx not in dev");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_DISABLE_DEV_REQUEST),
- 1, " request not cleared");
- /* Can still override with GBB flag */
- reset_common_data();
- cc.flags |= VB2_CONTEXT_RECOVERY_MODE;
- sd->status &= ~VB2_SD_STATUS_SECDATA_INIT;
- sd->gbb_flags |= VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON;
- TEST_SUCC(vb2_check_dev_switch(&cc), "secdata fail recovery gbb");
- TEST_NEQ(sd->flags & VB2_SD_DEV_MODE_ENABLED, 0, " sd in dev");
- TEST_NEQ(cc.flags & VB2_CONTEXT_DEVELOPER_MODE, 0, " ctx in dev");
- TEST_EQ(mock_tpm_clear_called, 1, " tpm clear");
- /* Can still override with context flag */
- reset_common_data();
- cc.flags |= VB2_CONTEXT_RECOVERY_MODE;
- cc.flags |= VB2_CONTEXT_FORCE_DEVELOPER_MODE;
- sd->status &= ~VB2_SD_STATUS_SECDATA_INIT;
- TEST_SUCC(vb2_check_dev_switch(&cc), "secdata fail recovery ctx");
- TEST_NEQ(sd->flags & VB2_SD_DEV_MODE_ENABLED, 0, " sd in dev");
- TEST_NEQ(cc.flags & VB2_CONTEXT_DEVELOPER_MODE, 0, " ctx in dev");
- TEST_EQ(mock_tpm_clear_called, 1, " tpm clear");
- }
- static void tpm_clear_tests(void)
- {
- /* No clear request */
- reset_common_data();
- TEST_SUCC(vb2_check_tpm_clear(&cc), "no clear request");
- TEST_EQ(mock_tpm_clear_called, 0, "tpm not cleared");
- /* Successful request */
- reset_common_data();
- vb2_nv_set(&cc, VB2_NV_CLEAR_TPM_OWNER_REQUEST, 1);
- TEST_SUCC(vb2_check_tpm_clear(&cc), "clear request");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_CLEAR_TPM_OWNER_REQUEST),
- 0, "request cleared");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_CLEAR_TPM_OWNER_DONE),
- 1, "done set");
- TEST_EQ(mock_tpm_clear_called, 1, "tpm cleared");
- /* Failed request */
- reset_common_data();
- mock_tpm_clear_retval = VB2_ERROR_EX_TPM_CLEAR_OWNER;
- vb2_nv_set(&cc, VB2_NV_CLEAR_TPM_OWNER_REQUEST, 1);
- TEST_EQ(vb2_check_tpm_clear(&cc),
- VB2_ERROR_EX_TPM_CLEAR_OWNER, "clear failure");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_CLEAR_TPM_OWNER_REQUEST),
- 0, "request cleared");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_CLEAR_TPM_OWNER_DONE),
- 0, "done not set");
- }
- static void select_slot_tests(void)
- {
- /* Slot A */
- reset_common_data();
- TEST_SUCC(vb2_select_fw_slot(&cc), "select slot A");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_RESULT),
- VB2_FW_RESULT_UNKNOWN, "result unknown");
- TEST_NEQ(sd->status & VB2_SD_STATUS_CHOSE_SLOT, 0, "chose slot");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_TRIED), 0, "tried A");
- TEST_EQ(sd->fw_slot, 0, "selected A");
- TEST_EQ(cc.flags & VB2_CONTEXT_FW_SLOT_B, 0, "didn't choose B");
- /* Slot B */
- reset_common_data();
- vb2_nv_set(&cc, VB2_NV_TRY_NEXT, 1);
- TEST_SUCC(vb2_select_fw_slot(&cc), "select slot B");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_RESULT),
- VB2_FW_RESULT_UNKNOWN, "result unknown");
- TEST_NEQ(sd->status & VB2_SD_STATUS_CHOSE_SLOT, 0, "chose slot");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_TRIED), 1, "tried B");
- TEST_EQ(sd->fw_slot, 1, "selected B");
- TEST_NEQ(cc.flags & VB2_CONTEXT_FW_SLOT_B, 0, "ctx says choose B");
- /* Slot A ran out of tries */
- reset_common_data();
- vb2_nv_set(&cc, VB2_NV_FW_RESULT, VB2_FW_RESULT_TRYING);
- TEST_SUCC(vb2_select_fw_slot(&cc), "select slot A out of tries");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_TRY_NEXT), 1, "try B next");
- TEST_NEQ(sd->status & VB2_SD_STATUS_CHOSE_SLOT, 0, "chose slot");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_TRIED), 1, "tried B");
- TEST_EQ(sd->fw_slot, 1, "selected B");
- TEST_NEQ(cc.flags & VB2_CONTEXT_FW_SLOT_B, 0, "ctx says choose B");
- /* Slot A ran out of tries, even with nofail active */
- reset_common_data();
- cc.flags |= VB2_CONTEXT_NOFAIL_BOOT;
- vb2_nv_set(&cc, VB2_NV_FW_RESULT, VB2_FW_RESULT_TRYING);
- TEST_SUCC(vb2_select_fw_slot(&cc), "select slot A out of tries");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_TRY_NEXT), 1, "try B next");
- TEST_NEQ(sd->status & VB2_SD_STATUS_CHOSE_SLOT, 0, "chose slot");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_TRIED), 1, "tried B");
- TEST_EQ(sd->fw_slot, 1, "selected B");
- TEST_NEQ(cc.flags & VB2_CONTEXT_FW_SLOT_B, 0, "ctx says choose B");
- /* Slot A used up a try */
- reset_common_data();
- vb2_nv_set(&cc, VB2_NV_TRY_COUNT, 3);
- TEST_SUCC(vb2_select_fw_slot(&cc), "try slot A");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_RESULT),
- VB2_FW_RESULT_TRYING, "result trying");
- TEST_NEQ(sd->status & VB2_SD_STATUS_CHOSE_SLOT, 0, "chose slot");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_TRIED), 0, "tried A");
- TEST_EQ(sd->fw_slot, 0, "selected A");
- TEST_EQ(cc.flags & VB2_CONTEXT_FW_SLOT_B, 0, "didn't choose B");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_TRY_COUNT), 2, "tries decremented");
- /* Slot A failed, but nofail active */
- reset_common_data();
- cc.flags |= VB2_CONTEXT_NOFAIL_BOOT;
- vb2_nv_set(&cc, VB2_NV_TRY_COUNT, 3);
- TEST_SUCC(vb2_select_fw_slot(&cc), "try slot A");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_RESULT),
- VB2_FW_RESULT_TRYING, "result trying");
- TEST_NEQ(sd->status & VB2_SD_STATUS_CHOSE_SLOT, 0, "chose slot");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_TRIED), 0, "tried A");
- TEST_EQ(sd->fw_slot, 0, "selected A");
- TEST_EQ(cc.flags & VB2_CONTEXT_FW_SLOT_B, 0, "didn't choose B");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_TRY_COUNT), 3, "tries not decremented");
- /* Tried/result get copied to the previous fields */
- reset_common_data();
- vb2_nv_set(&cc, VB2_NV_FW_TRIED, 0);
- vb2_nv_set(&cc, VB2_NV_FW_RESULT, VB2_FW_RESULT_SUCCESS);
- vb2_select_fw_slot(&cc);
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_PREV_TRIED), 0, "prev A");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_PREV_RESULT), VB2_FW_RESULT_SUCCESS,
- "prev success");
- reset_common_data();
- vb2_nv_set(&cc, VB2_NV_FW_TRIED, 1);
- vb2_nv_set(&cc, VB2_NV_FW_RESULT, VB2_FW_RESULT_FAILURE);
- vb2_select_fw_slot(&cc);
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_PREV_TRIED), 1, "prev B");
- TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_PREV_RESULT), VB2_FW_RESULT_FAILURE,
- "prev failure");
- }
- int main(int argc, char* argv[])
- {
- init_context_tests();
- misc_tests();
- gbb_tests();
- fail_tests();
- recovery_tests();
- dev_switch_tests();
- tpm_clear_tests();
- select_slot_tests();
- return gTestSuccess ? 0 : 255;
- }
|