| /* Copyright 2022 The ChromiumOS Authors | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| * | |
| * Tests for vb2_set_boot_mode. | |
| */ | |
| #include "2api.h" | |
| #include "2common.h" | |
| #include "2misc.h" | |
| #include "2nvstorage.h" | |
| #include "common/tests.h" | |
| /* Mock data */ | |
| static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE] | |
| __attribute__((aligned(VB2_WORKBUF_ALIGN))); | |
| static struct vb2_context *ctx; | |
| static struct vb2_shared_data *sd; | |
| static struct vb2_gbb_header gbb; | |
| static int mock_diagnostic_ui_enabled; | |
| /* Mock functions */ | |
| struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c) | |
| { | |
| return &gbb; | |
| } | |
| int vb2api_diagnostic_ui_enabled(struct vb2_context *c) | |
| { | |
| return mock_diagnostic_ui_enabled; | |
| } | |
| static void reset_common_data(void) | |
| { | |
| memset(workbuf, 0xaa, sizeof(workbuf)); | |
| memset(&gbb, 0, sizeof(gbb)); | |
| TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx), | |
| "vb2api_init failed"); | |
| sd = vb2_get_sd(ctx); | |
| vb2_nv_init(ctx); | |
| mock_diagnostic_ui_enabled = 0; | |
| } | |
| static void set_boot_mode_tests(void) | |
| { | |
| /* Normal boot */ | |
| reset_common_data(); | |
| vb2_set_boot_mode(ctx); | |
| TEST_EQ(ctx->boot_mode, VB2_BOOT_MODE_NORMAL, "Normal boot"); | |
| /* Check that NV_DIAG_REQUEST triggers diagnostic mode */ | |
| reset_common_data(); | |
| mock_diagnostic_ui_enabled = 1; | |
| vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 1); | |
| vb2_set_boot_mode(ctx); | |
| TEST_EQ(ctx->boot_mode, VB2_BOOT_MODE_DIAGNOSTICS, | |
| "Normal boot with diag UI enabled"); | |
| reset_common_data(); | |
| vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 1); | |
| vb2_set_boot_mode(ctx); | |
| TEST_EQ(ctx->boot_mode, VB2_BOOT_MODE_NORMAL, | |
| "Normal boot with diag UI disabled"); | |
| /* Developer boot */ | |
| reset_common_data(); | |
| ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE; | |
| sd->flags |= VB2_SD_FLAG_DEV_MODE_ENABLED; | |
| vb2_set_boot_mode(ctx); | |
| TEST_EQ(ctx->boot_mode, VB2_BOOT_MODE_DEVELOPER, "Dev boot"); | |
| /* Recovery boot */ | |
| reset_common_data(); | |
| sd->recovery_reason = 123; | |
| ctx->flags |= VB2_CONTEXT_RECOVERY_MODE; | |
| vb2_set_boot_mode(ctx); | |
| TEST_EQ(ctx->boot_mode, VB2_BOOT_MODE_BROKEN_SCREEN, "Broken screen"); | |
| reset_common_data(); | |
| sd->recovery_reason = VB2_RECOVERY_RO_MANUAL; | |
| ctx->flags |= VB2_CONTEXT_RECOVERY_MODE; | |
| gbb.flags |= VB2_GBB_FLAG_FORCE_MANUAL_RECOVERY; | |
| vb2_set_boot_mode(ctx); | |
| TEST_EQ(ctx->boot_mode, VB2_BOOT_MODE_MANUAL_RECOVERY, | |
| "Manual recovery: forced by GBB flags"); | |
| reset_common_data(); | |
| sd->recovery_reason = VB2_RECOVERY_RO_MANUAL; | |
| ctx->flags |= VB2_CONTEXT_FORCE_RECOVERY_MODE; | |
| ctx->flags |= VB2_CONTEXT_EC_TRUSTED; | |
| vb2_set_boot_mode(ctx); | |
| TEST_EQ(ctx->boot_mode, VB2_BOOT_MODE_MANUAL_RECOVERY, | |
| "Manual recovery: physical rec switch"); | |
| reset_common_data(); | |
| ctx->flags |= VB2_CONTEXT_EC_TRUSTED; | |
| vb2_set_boot_mode(ctx); | |
| TEST_NEQ(ctx->boot_mode, VB2_BOOT_MODE_MANUAL_RECOVERY, | |
| "VB2_CONTEXT_FORCE_RECOVERY_MODE is not set"); | |
| reset_common_data(); | |
| ctx->flags |= VB2_CONTEXT_FORCE_RECOVERY_MODE; | |
| ctx->flags |= VB2_CONTEXT_NO_BOOT; | |
| ctx->flags |= VB2_CONTEXT_EC_TRUSTED; | |
| vb2_set_boot_mode(ctx); | |
| TEST_NEQ(ctx->boot_mode, VB2_BOOT_MODE_MANUAL_RECOVERY, | |
| "Block manual recovery if NO_BOOT"); | |
| reset_common_data(); | |
| ctx->flags |= VB2_CONTEXT_FORCE_RECOVERY_MODE; | |
| vb2_set_boot_mode(ctx); | |
| TEST_NEQ(ctx->boot_mode, VB2_BOOT_MODE_MANUAL_RECOVERY, | |
| "Block manual recovery for untrusted EC"); | |
| } | |
| int main(void) | |
| { | |
| set_boot_mode_tests(); | |
| return gTestSuccess ? 0 : 255; | |
| } |