| /* Copyright 2019 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 auxfw synchronization. |
| */ |
| |
| #include <stdint.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| |
| #include "2common.h" |
| #include "2misc.h" |
| #include "2nvstorage.h" |
| #include "2sysincludes.h" |
| #include "host_common.h" |
| #include "load_kernel_fw.h" |
| #include "test_common.h" |
| #include "vboot_audio.h" |
| #include "vboot_display.h" |
| #include "vboot_kernel.h" |
| #include "vboot_struct.h" |
| |
| /* Mock data */ |
| static struct vb2_context *ctx; |
| static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE] |
| __attribute__((aligned(VB2_WORKBUF_ALIGN))); |
| static struct vb2_shared_data *sd; |
| static struct vb2_gbb_header gbb; |
| |
| static uint32_t screens_displayed[8]; |
| static uint32_t screens_count = 0; |
| |
| static vb2_error_t auxfw_retval; |
| static int auxfw_update_req; |
| static enum vb2_auxfw_update_severity auxfw_mock_severity; |
| static enum vb2_auxfw_update_severity auxfw_update_severity; |
| static int auxfw_protected; |
| static vb2_error_t auxfw_done_retval; |
| |
| /* Reset mock data (for use before each test) */ |
| static void ResetMocks(void) |
| { |
| TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx), |
| "vb2api_init failed"); |
| |
| ctx->flags = VB2_CONTEXT_EC_SYNC_SUPPORTED; |
| vb2_nv_init(ctx); |
| |
| sd = vb2_get_sd(ctx); |
| sd->flags |= VB2_SD_FLAG_DISPLAY_AVAILABLE; |
| |
| memset(&gbb, 0, sizeof(gbb)); |
| |
| memset(screens_displayed, 0, sizeof(screens_displayed)); |
| screens_count = 0; |
| |
| auxfw_retval = VB2_SUCCESS; |
| auxfw_mock_severity = VB_AUX_FW_NO_UPDATE; |
| auxfw_update_severity = VB_AUX_FW_NO_UPDATE; |
| auxfw_update_req = 0; |
| auxfw_protected = 0; |
| auxfw_done_retval = VB2_SUCCESS; |
| } |
| |
| /* Mock functions */ |
| struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c) |
| { |
| return &gbb; |
| } |
| |
| vb2_error_t VbDisplayScreen(struct vb2_context *c, uint32_t screen, int force, |
| const VbScreenData *data) |
| { |
| if (screens_count < ARRAY_SIZE(screens_displayed)) |
| screens_displayed[screens_count++] = screen; |
| |
| return VB2_SUCCESS; |
| } |
| |
| vb2_error_t vb2ex_auxfw_check(enum vb2_auxfw_update_severity *severity) |
| { |
| *severity = auxfw_mock_severity; |
| auxfw_update_severity = auxfw_mock_severity; |
| return VB2_SUCCESS; |
| } |
| |
| vb2_error_t vb2ex_auxfw_update(void) |
| { |
| if (auxfw_update_severity != VB_AUX_FW_NO_DEVICE && |
| auxfw_update_severity != VB_AUX_FW_NO_UPDATE) |
| auxfw_update_req = 1; |
| return auxfw_retval; |
| } |
| |
| vb2_error_t vb2ex_auxfw_finalize(struct vb2_context *c) |
| { |
| auxfw_protected = auxfw_update_severity != VB_AUX_FW_NO_DEVICE; |
| return auxfw_done_retval; |
| } |
| |
| static void test_auxsync(vb2_error_t retval, int recovery_reason, |
| const char *desc) |
| { |
| TEST_EQ(vb2api_auxfw_sync(ctx), retval, desc); |
| TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), |
| recovery_reason, " recovery reason"); |
| } |
| |
| /* Tests */ |
| |
| static void VbSoftwareSyncTest(void) |
| { |
| ResetMocks(); |
| gbb.flags |= VB2_GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC; |
| auxfw_mock_severity = VB_AUX_FW_FAST_UPDATE; |
| test_auxsync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, 0, |
| "VB2_GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC" |
| " does not disable auxiliary FW update request"); |
| TEST_EQ(auxfw_update_req, 1, " aux fw update requested"); |
| TEST_EQ(auxfw_protected, 0, " aux fw protected"); |
| |
| ResetMocks(); |
| gbb.flags |= VB2_GBB_FLAG_DISABLE_AUXFW_SOFTWARE_SYNC; |
| auxfw_mock_severity = VB_AUX_FW_FAST_UPDATE; |
| test_auxsync(VB2_SUCCESS, 0, |
| "VB2_GBB_FLAG_DISABLE_AUXFW_SOFTWARE_SYNC" |
| " disables auxiliary FW update request"); |
| TEST_EQ(auxfw_update_req, 0, " aux fw update disabled"); |
| TEST_EQ(auxfw_protected, 1, " aux fw protected"); |
| |
| ResetMocks(); |
| auxfw_mock_severity = VB_AUX_FW_NO_DEVICE; |
| test_auxsync(VB2_SUCCESS, 0, |
| "No auxiliary FW update needed"); |
| TEST_EQ(screens_count, 0, |
| " wait screen skipped"); |
| TEST_EQ(auxfw_update_req, 0, " no aux fw update requested"); |
| TEST_EQ(auxfw_protected, 0, " no aux fw protected"); |
| |
| ResetMocks(); |
| auxfw_mock_severity = VB_AUX_FW_NO_UPDATE; |
| test_auxsync(VB2_SUCCESS, 0, |
| "No auxiliary FW update needed"); |
| TEST_EQ(screens_count, 0, |
| " wait screen skipped"); |
| TEST_EQ(auxfw_update_req, 0, " no aux fw update requested"); |
| TEST_EQ(auxfw_protected, 1, " aux fw protected"); |
| |
| ResetMocks(); |
| auxfw_mock_severity = VB_AUX_FW_FAST_UPDATE; |
| test_auxsync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, 0, |
| "Fast auxiliary FW update needed"); |
| TEST_EQ(screens_count, 0, |
| " wait screen skipped"); |
| TEST_EQ(auxfw_update_req, 1, " aux fw update requested"); |
| TEST_EQ(auxfw_protected, 0, " aux fw protected"); |
| |
| ResetMocks(); |
| auxfw_mock_severity = VB_AUX_FW_SLOW_UPDATE; |
| sd->flags &= ~VB2_SD_FLAG_DISPLAY_AVAILABLE; |
| test_auxsync(VBERROR_REBOOT_REQUIRED, 0, |
| "Slow auxiliary FW update needed - reboot for display"); |
| |
| ResetMocks(); |
| auxfw_mock_severity = VB_AUX_FW_SLOW_UPDATE; |
| test_auxsync(VBERROR_EC_REBOOT_TO_RO_REQUIRED, 0, |
| "Slow auxiliary FW update needed"); |
| TEST_EQ(auxfw_update_req, 1, " aux fw update requested"); |
| TEST_EQ(auxfw_protected, 0, " aux fw protected"); |
| TEST_EQ(screens_displayed[0], VB_SCREEN_WAIT, |
| " wait screen forced"); |
| |
| ResetMocks(); |
| auxfw_mock_severity = VB_AUX_FW_FAST_UPDATE; |
| auxfw_retval = VB2_ERROR_UNKNOWN; |
| test_auxsync(VB2_ERROR_UNKNOWN, VB2_RECOVERY_AUX_FW_UPDATE, |
| "Error updating AUX firmware"); |
| } |
| |
| int main(void) |
| { |
| VbSoftwareSyncTest(); |
| |
| return gTestSuccess ? 0 : 255; |
| } |