mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-24 18:25:10 +00:00
vboot: Split ec software sync to its own file
This was previously done inside vboot_api_kernel. But it has nothing to do with kernel verification; that's just the only place where we could easily put it given that vboot (currently) owns the firmware UI. No outwardly-visible functionality changes. BUG=chromium:611535 BRANCH=none TEST=make runtests; emerge-kevin coreboot depthcharge Change-Id: I8a434eb4449a5a86b129ecac61ad81d0ad55549c Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/404920
This commit is contained in:
committed by
chrome-bot
parent
e5500a319b
commit
2603675460
5
Makefile
5
Makefile
@@ -331,6 +331,7 @@ VBSLK_SRCS = \
|
|||||||
firmware/lib/cgptlib/cgptlib.c \
|
firmware/lib/cgptlib/cgptlib.c \
|
||||||
firmware/lib/cgptlib/cgptlib_internal.c \
|
firmware/lib/cgptlib/cgptlib_internal.c \
|
||||||
firmware/lib/cgptlib/crc32.c \
|
firmware/lib/cgptlib/crc32.c \
|
||||||
|
firmware/lib/ec_sync.c \
|
||||||
firmware/lib/gpt_misc.c \
|
firmware/lib/gpt_misc.c \
|
||||||
firmware/lib/utility_string.c \
|
firmware/lib/utility_string.c \
|
||||||
firmware/lib/vboot_api_kernel.c \
|
firmware/lib/vboot_api_kernel.c \
|
||||||
@@ -711,6 +712,7 @@ TEST_OBJS += ${TESTLIB_OBJS}
|
|||||||
# And some compiled tests.
|
# And some compiled tests.
|
||||||
TEST_NAMES = \
|
TEST_NAMES = \
|
||||||
tests/cgptlib_test \
|
tests/cgptlib_test \
|
||||||
|
tests/ec_sync_tests \
|
||||||
tests/rollback_index3_tests \
|
tests/rollback_index3_tests \
|
||||||
tests/sha_benchmark \
|
tests/sha_benchmark \
|
||||||
tests/utility_string_tests \
|
tests/utility_string_tests \
|
||||||
@@ -718,7 +720,6 @@ TEST_NAMES = \
|
|||||||
tests/vboot_api_devmode_tests \
|
tests/vboot_api_devmode_tests \
|
||||||
tests/vboot_api_kernel_tests \
|
tests/vboot_api_kernel_tests \
|
||||||
tests/vboot_api_kernel2_tests \
|
tests/vboot_api_kernel2_tests \
|
||||||
tests/vboot_api_kernel3_tests \
|
|
||||||
tests/vboot_api_kernel4_tests \
|
tests/vboot_api_kernel4_tests \
|
||||||
tests/vboot_api_kernel5_tests \
|
tests/vboot_api_kernel5_tests \
|
||||||
tests/vboot_api_kernel6_tests \
|
tests/vboot_api_kernel6_tests \
|
||||||
@@ -1401,6 +1402,7 @@ runtestscripts: test_setup genfuzztestcases
|
|||||||
|
|
||||||
.PHONY: runmisctests
|
.PHONY: runmisctests
|
||||||
runmisctests: test_setup
|
runmisctests: test_setup
|
||||||
|
${RUNTEST} ${BUILD_RUN}/tests/ec_sync_tests
|
||||||
ifeq (${TPM2_MODE},)
|
ifeq (${TPM2_MODE},)
|
||||||
${RUNTEST} ${BUILD_RUN}/tests/tlcl_tests
|
${RUNTEST} ${BUILD_RUN}/tests/tlcl_tests
|
||||||
${RUNTEST} ${BUILD_RUN}/tests/rollback_index2_tests
|
${RUNTEST} ${BUILD_RUN}/tests/rollback_index2_tests
|
||||||
@@ -1411,7 +1413,6 @@ endif
|
|||||||
${RUNTEST} ${BUILD_RUN}/tests/vboot_api_devmode_tests
|
${RUNTEST} ${BUILD_RUN}/tests/vboot_api_devmode_tests
|
||||||
${RUNTEST} ${BUILD_RUN}/tests/vboot_api_kernel_tests
|
${RUNTEST} ${BUILD_RUN}/tests/vboot_api_kernel_tests
|
||||||
${RUNTEST} ${BUILD_RUN}/tests/vboot_api_kernel2_tests
|
${RUNTEST} ${BUILD_RUN}/tests/vboot_api_kernel2_tests
|
||||||
${RUNTEST} ${BUILD_RUN}/tests/vboot_api_kernel3_tests
|
|
||||||
${RUNTEST} ${BUILD_RUN}/tests/vboot_api_kernel4_tests
|
${RUNTEST} ${BUILD_RUN}/tests/vboot_api_kernel4_tests
|
||||||
${RUNTEST} ${BUILD_RUN}/tests/vboot_api_kernel5_tests
|
${RUNTEST} ${BUILD_RUN}/tests/vboot_api_kernel5_tests
|
||||||
${RUNTEST} ${BUILD_RUN}/tests/vboot_api_kernel6_tests
|
${RUNTEST} ${BUILD_RUN}/tests/vboot_api_kernel6_tests
|
||||||
|
|||||||
387
firmware/lib/ec_sync.c
Normal file
387
firmware/lib/ec_sync.c
Normal file
@@ -0,0 +1,387 @@
|
|||||||
|
/* Copyright (c) 2013 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.
|
||||||
|
*
|
||||||
|
* EC software sync routines for vboot
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "2sysincludes.h"
|
||||||
|
#include "2common.h"
|
||||||
|
#include "sysincludes.h"
|
||||||
|
#include "utility.h"
|
||||||
|
#include "vb2_common.h"
|
||||||
|
#include "vboot_api.h"
|
||||||
|
#include "vboot_common.h"
|
||||||
|
#include "vboot_display.h"
|
||||||
|
#include "vboot_kernel.h"
|
||||||
|
#include "vboot_nvstorage.h"
|
||||||
|
|
||||||
|
static void request_recovery(VbNvContext *vnc, uint32_t recovery_request)
|
||||||
|
{
|
||||||
|
VB2_DEBUG("request_recovery(%d)\n", (int)recovery_request);
|
||||||
|
|
||||||
|
VbNvSet(vnc, VBNV_RECOVERY_REQUEST, recovery_request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper around VbExEcProtect() which sets recovery reason on error.
|
||||||
|
*/
|
||||||
|
static VbError_t EcProtect(int devidx, enum VbSelectFirmware_t select,
|
||||||
|
VbNvContext *vnc)
|
||||||
|
{
|
||||||
|
int rv = VbExEcProtect(devidx, select);
|
||||||
|
|
||||||
|
if (rv == VBERROR_EC_REBOOT_TO_RO_REQUIRED) {
|
||||||
|
VBDEBUG(("VbExEcProtect() needs reboot\n"));
|
||||||
|
} else if (rv != VBERROR_SUCCESS) {
|
||||||
|
VBDEBUG(("VbExEcProtect() returned %d\n", rv));
|
||||||
|
request_recovery(vnc, VBNV_RECOVERY_EC_PROTECT);
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VbError_t EcUpdateImage(int devidx, VbCommonParams *cparams,
|
||||||
|
enum VbSelectFirmware_t select,
|
||||||
|
int *need_update, int in_rw, VbNvContext *vnc)
|
||||||
|
{
|
||||||
|
VbSharedDataHeader *shared =
|
||||||
|
(VbSharedDataHeader *)cparams->shared_data_blob;
|
||||||
|
int rv;
|
||||||
|
int hash_size;
|
||||||
|
int ec_hash_size;
|
||||||
|
const uint8_t *hash = NULL;
|
||||||
|
const uint8_t *expected = NULL;
|
||||||
|
const uint8_t *ec_hash = NULL;
|
||||||
|
int expected_size;
|
||||||
|
int i;
|
||||||
|
int rw_request = select != VB_SELECT_FIRMWARE_READONLY;
|
||||||
|
|
||||||
|
*need_update = 0;
|
||||||
|
VBDEBUG(("EcUpdateImage() - "
|
||||||
|
"Check for %s update\n", rw_request ? "RW" : "RO"));
|
||||||
|
|
||||||
|
/* Get current EC hash. */
|
||||||
|
rv = VbExEcHashImage(devidx, select, &ec_hash, &ec_hash_size);
|
||||||
|
if (rv) {
|
||||||
|
VBDEBUG(("EcUpdateImage() - "
|
||||||
|
"VbExEcHashImage() returned %d\n", rv));
|
||||||
|
request_recovery(vnc, VBNV_RECOVERY_EC_HASH_FAILED);
|
||||||
|
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
||||||
|
}
|
||||||
|
VBDEBUG(("EC-%s hash: ", rw_request ? "RW" : "RO"));
|
||||||
|
for (i = 0; i < ec_hash_size; i++)
|
||||||
|
VBDEBUG(("%02x",ec_hash[i]));
|
||||||
|
VBDEBUG(("\n"));
|
||||||
|
|
||||||
|
/* Get expected EC hash. */
|
||||||
|
rv = VbExEcGetExpectedImageHash(devidx, select, &hash, &hash_size);
|
||||||
|
if (rv) {
|
||||||
|
VBDEBUG(("EcUpdateImage() - "
|
||||||
|
"VbExEcGetExpectedImageHash() returned %d\n", rv));
|
||||||
|
request_recovery(vnc, VBNV_RECOVERY_EC_EXPECTED_HASH);
|
||||||
|
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
||||||
|
}
|
||||||
|
if (ec_hash_size != hash_size) {
|
||||||
|
VBDEBUG(("EcUpdateImage() - "
|
||||||
|
"EC uses %d-byte hash, but AP-RW contains %d bytes\n",
|
||||||
|
ec_hash_size, hash_size));
|
||||||
|
request_recovery(vnc, VBNV_RECOVERY_EC_HASH_SIZE);
|
||||||
|
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
VBDEBUG(("Expected hash: "));
|
||||||
|
for (i = 0; i < hash_size; i++)
|
||||||
|
VBDEBUG(("%02x", hash[i]));
|
||||||
|
VBDEBUG(("\n"));
|
||||||
|
*need_update = vb2_safe_memcmp(ec_hash, hash, hash_size);
|
||||||
|
|
||||||
|
if (!*need_update)
|
||||||
|
return VBERROR_SUCCESS;
|
||||||
|
|
||||||
|
/* Get expected EC image */
|
||||||
|
rv = VbExEcGetExpectedImage(devidx, select, &expected, &expected_size);
|
||||||
|
if (rv) {
|
||||||
|
VBDEBUG(("EcUpdateImage() - "
|
||||||
|
"VbExEcGetExpectedImage() returned %d\n", rv));
|
||||||
|
request_recovery(vnc, VBNV_RECOVERY_EC_EXPECTED_IMAGE);
|
||||||
|
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
||||||
|
}
|
||||||
|
VBDEBUG(("EcUpdateImage() - image len = %d\n", expected_size));
|
||||||
|
|
||||||
|
if (in_rw && rw_request) {
|
||||||
|
/*
|
||||||
|
* Check if BIOS should also load VGA Option ROM when
|
||||||
|
* rebooting to save another reboot if possible.
|
||||||
|
*/
|
||||||
|
if ((shared->flags & VBSD_EC_SLOW_UPDATE) &&
|
||||||
|
(shared->flags & VBSD_OPROM_MATTERS) &&
|
||||||
|
!(shared->flags & VBSD_OPROM_LOADED)) {
|
||||||
|
VBDEBUG(("EcUpdateImage() - Reboot to "
|
||||||
|
"load VGA Option ROM\n"));
|
||||||
|
VbNvSet(vnc, VBNV_OPROM_NEEDED, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EC is running the wrong RW image. Reboot the EC to
|
||||||
|
* RO so we can update it on the next boot.
|
||||||
|
*/
|
||||||
|
VBDEBUG(("EcUpdateImage() - "
|
||||||
|
"in RW, need to update RW, so reboot\n"));
|
||||||
|
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
VBDEBUG(("EcUpdateImage() updating EC-%s...\n",
|
||||||
|
rw_request ? "RW" : "RO"));
|
||||||
|
|
||||||
|
if (shared->flags & VBSD_EC_SLOW_UPDATE) {
|
||||||
|
VBDEBUG(("EcUpdateImage() - EC is slow. Show WAIT screen.\n"));
|
||||||
|
|
||||||
|
/* Ensure the VGA Option ROM is loaded */
|
||||||
|
if ((shared->flags & VBSD_OPROM_MATTERS) &&
|
||||||
|
!(shared->flags & VBSD_OPROM_LOADED)) {
|
||||||
|
VBDEBUG(("EcUpdateImage() - Reboot to "
|
||||||
|
"load VGA Option ROM\n"));
|
||||||
|
VbNvSet(vnc, VBNV_OPROM_NEEDED, 1);
|
||||||
|
return VBERROR_VGA_OPROM_MISMATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
VbDisplayScreen(cparams, VB_SCREEN_WAIT, 0, vnc);
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = VbExEcUpdateImage(devidx, select, expected, expected_size);
|
||||||
|
if (rv != VBERROR_SUCCESS) {
|
||||||
|
VBDEBUG(("EcUpdateImage() - "
|
||||||
|
"VbExEcUpdateImage() returned %d\n", rv));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The EC may know it needs a reboot. It may need to
|
||||||
|
* unprotect the region before updating, or may need to
|
||||||
|
* reboot after updating. Either way, it's not an error
|
||||||
|
* requiring recovery mode.
|
||||||
|
*
|
||||||
|
* If we fail for any other reason, trigger recovery
|
||||||
|
* mode.
|
||||||
|
*/
|
||||||
|
if (rv != VBERROR_EC_REBOOT_TO_RO_REQUIRED)
|
||||||
|
request_recovery(vnc, VBNV_RECOVERY_EC_UPDATE);
|
||||||
|
|
||||||
|
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify the EC was updated properly */
|
||||||
|
rv = VbExEcHashImage(devidx, select, &ec_hash, &ec_hash_size);
|
||||||
|
if (rv) {
|
||||||
|
VBDEBUG(("EcUpdateImage() - "
|
||||||
|
"VbExEcHashImage() returned %d\n", rv));
|
||||||
|
request_recovery(vnc, VBNV_RECOVERY_EC_HASH_FAILED);
|
||||||
|
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
||||||
|
}
|
||||||
|
if (hash_size != ec_hash_size) {
|
||||||
|
VBDEBUG(("EcUpdateImage() - "
|
||||||
|
"VbExEcHashImage() says size %d, not %d\n",
|
||||||
|
ec_hash_size, hash_size));
|
||||||
|
request_recovery(vnc, VBNV_RECOVERY_EC_HASH_SIZE);
|
||||||
|
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
||||||
|
}
|
||||||
|
VBDEBUG(("Updated EC-%s hash: ", rw_request ? "RW" : "RO"));
|
||||||
|
for (i = 0; i < ec_hash_size; i++)
|
||||||
|
VBDEBUG(("%02x",ec_hash[i]));
|
||||||
|
VBDEBUG(("\n"));
|
||||||
|
|
||||||
|
if (vb2_safe_memcmp(ec_hash, hash, hash_size)){
|
||||||
|
VBDEBUG(("EcUpdateImage() - "
|
||||||
|
"Failed to update EC-%s\n", rw_request ?
|
||||||
|
"RW" : "RO"));
|
||||||
|
request_recovery(vnc, VBNV_RECOVERY_EC_UPDATE);
|
||||||
|
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return VBERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
VbError_t VbEcSoftwareSync(int devidx, VbCommonParams *cparams,
|
||||||
|
VbNvContext *vnc)
|
||||||
|
{
|
||||||
|
VbSharedDataHeader *shared =
|
||||||
|
(VbSharedDataHeader *)cparams->shared_data_blob;
|
||||||
|
enum VbSelectFirmware_t select_rw =
|
||||||
|
shared->firmware_index ? VB_SELECT_FIRMWARE_B :
|
||||||
|
VB_SELECT_FIRMWARE_A;
|
||||||
|
enum VbSelectFirmware_t select_ro = VB_SELECT_FIRMWARE_READONLY;
|
||||||
|
int in_rw = 0;
|
||||||
|
int ro_try_count = 2;
|
||||||
|
int num_tries = 0;
|
||||||
|
uint32_t try_ro_sync, recovery_request;
|
||||||
|
int rv, updated_rw, updated_ro;
|
||||||
|
|
||||||
|
VBDEBUG(("VbEcSoftwareSync(devidx=%d)\n", devidx));
|
||||||
|
|
||||||
|
/* Determine whether the EC is in RO or RW */
|
||||||
|
rv = VbExEcRunningRW(devidx, &in_rw);
|
||||||
|
|
||||||
|
if (shared->recovery_reason) {
|
||||||
|
/* Recovery mode; just verify the EC is in RO code */
|
||||||
|
if (rv == VBERROR_SUCCESS && in_rw == 1) {
|
||||||
|
/*
|
||||||
|
* EC is definitely in RW firmware. We want it in
|
||||||
|
* read-only code, so preserve the current recovery
|
||||||
|
* reason and reboot.
|
||||||
|
*
|
||||||
|
* We don't reboot on error or unknown EC code, because
|
||||||
|
* we could end up in an endless reboot loop. If we
|
||||||
|
* had some way to track that we'd already rebooted for
|
||||||
|
* this reason, we could retry only once.
|
||||||
|
*/
|
||||||
|
VBDEBUG(("VbEcSoftwareSync() - "
|
||||||
|
"want recovery but got EC-RW\n"));
|
||||||
|
request_recovery(vnc, shared->recovery_reason);
|
||||||
|
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
VBDEBUG(("VbEcSoftwareSync() in recovery; EC-RO\n"));
|
||||||
|
return VBERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Not in recovery. If we couldn't determine where the EC was,
|
||||||
|
* reboot to recovery.
|
||||||
|
*/
|
||||||
|
if (rv != VBERROR_SUCCESS) {
|
||||||
|
VBDEBUG(("VbEcSoftwareSync() - "
|
||||||
|
"VbExEcRunningRW() returned %d\n", rv));
|
||||||
|
request_recovery(vnc, VBNV_RECOVERY_EC_UNKNOWN_IMAGE);
|
||||||
|
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If AP is read-only normal, EC should be in its RO code also. */
|
||||||
|
if (shared->flags & VBSD_LF_USE_RO_NORMAL) {
|
||||||
|
/* If EC is in RW code, request reboot back to RO */
|
||||||
|
if (in_rw == 1) {
|
||||||
|
VBDEBUG(("VbEcSoftwareSync() - "
|
||||||
|
"want RO-normal but got EC-RW\n"));
|
||||||
|
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Protect the RW flash and stay in EC-RO */
|
||||||
|
rv = EcProtect(devidx, select_rw, vnc);
|
||||||
|
if (rv != VBERROR_SUCCESS)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
rv = VbExEcDisableJump(devidx);
|
||||||
|
if (rv != VBERROR_SUCCESS) {
|
||||||
|
VBDEBUG(("VbEcSoftwareSync() - "
|
||||||
|
"VbExEcDisableJump() returned %d\n", rv));
|
||||||
|
request_recovery(vnc, VBNV_RECOVERY_EC_SOFTWARE_SYNC);
|
||||||
|
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
VBDEBUG(("VbEcSoftwareSync() in RO-Normal; EC-RO\n"));
|
||||||
|
return VBERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
VBDEBUG(("VbEcSoftwareSync() check for RW update.\n"));
|
||||||
|
|
||||||
|
/* Update the RW Image. */
|
||||||
|
rv = EcUpdateImage(devidx, cparams, select_rw, &updated_rw, in_rw, vnc);
|
||||||
|
|
||||||
|
if (rv != VBERROR_SUCCESS) {
|
||||||
|
VBDEBUG(("VbEcSoftwareSync() - "
|
||||||
|
"EcUpdateImage() returned %d\n", rv));
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tell EC to jump to its RW image */
|
||||||
|
if (!in_rw) {
|
||||||
|
VBDEBUG(("VbEcSoftwareSync() jumping to EC-RW\n"));
|
||||||
|
rv = VbExEcJumpToRW(devidx);
|
||||||
|
if (rv != VBERROR_SUCCESS) {
|
||||||
|
VBDEBUG(("VbEcSoftwareSync() - "
|
||||||
|
"VbExEcJumpToRW() returned %x\n", rv));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the EC booted RO-normal and a previous AP boot
|
||||||
|
* has called VbExEcStayInRO(), we need to reboot the EC
|
||||||
|
* to unlock the ability to jump to the RW firmware.
|
||||||
|
*
|
||||||
|
* All other errors trigger recovery mode.
|
||||||
|
*/
|
||||||
|
if (rv != VBERROR_EC_REBOOT_TO_RO_REQUIRED)
|
||||||
|
request_recovery(vnc, VBNV_RECOVERY_EC_JUMP_RW);
|
||||||
|
|
||||||
|
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VbNvGet(vnc, VBNV_TRY_RO_SYNC, &try_ro_sync);
|
||||||
|
|
||||||
|
if (!devidx && try_ro_sync &&
|
||||||
|
!(shared->flags & VBSD_BOOT_FIRMWARE_WP_ENABLED)) {
|
||||||
|
/* Reset RO Software Sync NV flag */
|
||||||
|
VbNvSet(vnc, VBNV_TRY_RO_SYNC, 0);
|
||||||
|
|
||||||
|
VbNvGet(vnc, VBNV_RECOVERY_REQUEST, &recovery_request);
|
||||||
|
|
||||||
|
/* Update the RO Image. */
|
||||||
|
while (num_tries < ro_try_count) {
|
||||||
|
VBDEBUG(("VbEcSoftwareSync() RO Software Sync\n"));
|
||||||
|
|
||||||
|
/* Get expected EC-RO Image. */
|
||||||
|
rv = EcUpdateImage(devidx, cparams, select_ro,
|
||||||
|
&updated_ro, in_rw, vnc);
|
||||||
|
if (rv == VBERROR_SUCCESS) {
|
||||||
|
/*
|
||||||
|
* If the RO update had failed, reset the
|
||||||
|
* recovery request.
|
||||||
|
*/
|
||||||
|
if (num_tries)
|
||||||
|
request_recovery(vnc, recovery_request);
|
||||||
|
break;
|
||||||
|
} else
|
||||||
|
VBDEBUG(("VbEcSoftwareSync() - "
|
||||||
|
"EcUpdateImage() returned %d\n", rv));
|
||||||
|
|
||||||
|
num_tries++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rv != VBERROR_SUCCESS)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
/* Protect RO flash */
|
||||||
|
rv = EcProtect(devidx, select_ro, vnc);
|
||||||
|
if (rv != VBERROR_SUCCESS)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
/* Protect RW flash */
|
||||||
|
rv = EcProtect(devidx, select_rw, vnc);
|
||||||
|
if (rv != VBERROR_SUCCESS)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
rv = VbExEcDisableJump(devidx);
|
||||||
|
if (rv != VBERROR_SUCCESS) {
|
||||||
|
VBDEBUG(("VbEcSoftwareSync() - "
|
||||||
|
"VbExEcDisableJump() returned %d\n", rv));
|
||||||
|
request_recovery(vnc, VBNV_RECOVERY_EC_SOFTWARE_SYNC);
|
||||||
|
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reboot to unload VGA Option ROM if:
|
||||||
|
* - RW update was done
|
||||||
|
* - the system is NOT in developer mode
|
||||||
|
* - the system has slow EC update flag set
|
||||||
|
* - the VGA Option ROM was needed and loaded
|
||||||
|
*/
|
||||||
|
if (updated_rw &&
|
||||||
|
!(shared->flags & VBSD_BOOT_DEV_SWITCH_ON) &&
|
||||||
|
(shared->flags & VBSD_EC_SLOW_UPDATE) &&
|
||||||
|
(shared->flags & VBSD_OPROM_MATTERS) &&
|
||||||
|
(shared->flags & VBSD_OPROM_LOADED)) {
|
||||||
|
VBDEBUG(("VbEcSoftwareSync() - Reboot to "
|
||||||
|
"unload VGA Option ROM\n"));
|
||||||
|
VbNvSet(vnc, VBNV_OPROM_NEEDED, 0);
|
||||||
|
return VBERROR_VGA_OPROM_MISMATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
@@ -67,7 +67,12 @@ VbError_t VbBootRecovery(VbCommonParams *cparams, LoadKernelParams *p);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sync EC device <devidx> firmware to expected version.
|
* Sync EC device <devidx> firmware to expected version.
|
||||||
|
*
|
||||||
|
* @param devidx EC device index to sync
|
||||||
|
* @param cparams Common vboot params
|
||||||
|
* @param vnc NV storage context
|
||||||
*/
|
*/
|
||||||
VbError_t VbEcSoftwareSync(int devidx, VbCommonParams *cparams);
|
VbError_t VbEcSoftwareSync(int devidx, VbCommonParams *cparams,
|
||||||
|
VbNvContext *vnc);
|
||||||
|
|
||||||
#endif /* VBOOT_REFERENCE_VBOOT_KERNEL_H_ */
|
#endif /* VBOOT_REFERENCE_VBOOT_KERNEL_H_ */
|
||||||
|
|||||||
@@ -57,6 +57,12 @@ static void VbSetRecoverySubcode(uint32_t recovery_request)
|
|||||||
VbNvSet(&vnc, VBNV_RECOVERY_SUBCODE, recovery_request);
|
VbNvSet(&vnc, VBNV_RECOVERY_SUBCODE, recovery_request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void VbNvLoad(void)
|
||||||
|
{
|
||||||
|
VbExNvStorageRead(vnc.raw);
|
||||||
|
VbNvSetup(&vnc);
|
||||||
|
}
|
||||||
|
|
||||||
static void VbNvCommit(void)
|
static void VbNvCommit(void)
|
||||||
{
|
{
|
||||||
VbNvTeardown(&vnc);
|
VbNvTeardown(&vnc);
|
||||||
@@ -694,367 +700,6 @@ VbError_t VbBootRecovery(VbCommonParams *cparams, LoadKernelParams *p)
|
|||||||
return VBERROR_SUCCESS;
|
return VBERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrapper around VbExEcProtect() which sets recovery reason on error.
|
|
||||||
*/
|
|
||||||
static VbError_t EcProtect(int devidx, enum VbSelectFirmware_t select)
|
|
||||||
{
|
|
||||||
int rv = VbExEcProtect(devidx, select);
|
|
||||||
|
|
||||||
if (rv == VBERROR_EC_REBOOT_TO_RO_REQUIRED) {
|
|
||||||
VBDEBUG(("VbExEcProtect() needs reboot\n"));
|
|
||||||
} else if (rv != VBERROR_SUCCESS) {
|
|
||||||
VBDEBUG(("VbExEcProtect() returned %d\n", rv));
|
|
||||||
VbSetRecoveryRequest(VBNV_RECOVERY_EC_PROTECT);
|
|
||||||
}
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static VbError_t EcUpdateImage(int devidx, VbCommonParams *cparams,
|
|
||||||
enum VbSelectFirmware_t select,
|
|
||||||
int *need_update, int in_rw)
|
|
||||||
{
|
|
||||||
VbSharedDataHeader *shared =
|
|
||||||
(VbSharedDataHeader *)cparams->shared_data_blob;
|
|
||||||
int rv;
|
|
||||||
int hash_size;
|
|
||||||
int ec_hash_size;
|
|
||||||
const uint8_t *hash = NULL;
|
|
||||||
const uint8_t *expected = NULL;
|
|
||||||
const uint8_t *ec_hash = NULL;
|
|
||||||
int expected_size;
|
|
||||||
int i;
|
|
||||||
int rw_request = select != VB_SELECT_FIRMWARE_READONLY;
|
|
||||||
|
|
||||||
*need_update = 0;
|
|
||||||
VBDEBUG(("EcUpdateImage() - "
|
|
||||||
"Check for %s update\n", rw_request ? "RW" : "RO"));
|
|
||||||
|
|
||||||
/* Get current EC hash. */
|
|
||||||
rv = VbExEcHashImage(devidx, select, &ec_hash, &ec_hash_size);
|
|
||||||
if (rv) {
|
|
||||||
VBDEBUG(("EcUpdateImage() - "
|
|
||||||
"VbExEcHashImage() returned %d\n", rv));
|
|
||||||
VbSetRecoveryRequest(VBNV_RECOVERY_EC_HASH_FAILED);
|
|
||||||
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
|
||||||
}
|
|
||||||
VBDEBUG(("EC-%s hash: ", rw_request ? "RW" : "RO"));
|
|
||||||
for (i = 0; i < ec_hash_size; i++)
|
|
||||||
VBDEBUG(("%02x",ec_hash[i]));
|
|
||||||
VBDEBUG(("\n"));
|
|
||||||
|
|
||||||
/* Get expected EC hash. */
|
|
||||||
rv = VbExEcGetExpectedImageHash(devidx, select, &hash, &hash_size);
|
|
||||||
if (rv) {
|
|
||||||
VBDEBUG(("EcUpdateImage() - "
|
|
||||||
"VbExEcGetExpectedImageHash() returned %d\n", rv));
|
|
||||||
VbSetRecoveryRequest(VBNV_RECOVERY_EC_EXPECTED_HASH);
|
|
||||||
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
|
||||||
}
|
|
||||||
if (ec_hash_size != hash_size) {
|
|
||||||
VBDEBUG(("EcUpdateImage() - "
|
|
||||||
"EC uses %d-byte hash, but AP-RW contains %d bytes\n",
|
|
||||||
ec_hash_size, hash_size));
|
|
||||||
VbSetRecoveryRequest(VBNV_RECOVERY_EC_HASH_SIZE);
|
|
||||||
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
|
||||||
}
|
|
||||||
|
|
||||||
VBDEBUG(("Expected hash: "));
|
|
||||||
for (i = 0; i < hash_size; i++)
|
|
||||||
VBDEBUG(("%02x", hash[i]));
|
|
||||||
VBDEBUG(("\n"));
|
|
||||||
*need_update = vb2_safe_memcmp(ec_hash, hash, hash_size);
|
|
||||||
|
|
||||||
if (!*need_update)
|
|
||||||
return VBERROR_SUCCESS;
|
|
||||||
|
|
||||||
/* Get expected EC image */
|
|
||||||
rv = VbExEcGetExpectedImage(devidx, select, &expected, &expected_size);
|
|
||||||
if (rv) {
|
|
||||||
VBDEBUG(("EcUpdateImage() - "
|
|
||||||
"VbExEcGetExpectedImage() returned %d\n", rv));
|
|
||||||
VbSetRecoveryRequest(VBNV_RECOVERY_EC_EXPECTED_IMAGE);
|
|
||||||
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
|
||||||
}
|
|
||||||
VBDEBUG(("EcUpdateImage() - image len = %d\n", expected_size));
|
|
||||||
|
|
||||||
if (in_rw && rw_request) {
|
|
||||||
/*
|
|
||||||
* Check if BIOS should also load VGA Option ROM when
|
|
||||||
* rebooting to save another reboot if possible.
|
|
||||||
*/
|
|
||||||
if ((shared->flags & VBSD_EC_SLOW_UPDATE) &&
|
|
||||||
(shared->flags & VBSD_OPROM_MATTERS) &&
|
|
||||||
!(shared->flags & VBSD_OPROM_LOADED)) {
|
|
||||||
VBDEBUG(("EcUpdateImage() - Reboot to "
|
|
||||||
"load VGA Option ROM\n"));
|
|
||||||
VbNvSet(&vnc, VBNV_OPROM_NEEDED, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* EC is running the wrong RW image. Reboot the EC to
|
|
||||||
* RO so we can update it on the next boot.
|
|
||||||
*/
|
|
||||||
VBDEBUG(("EcUpdateImage() - "
|
|
||||||
"in RW, need to update RW, so reboot\n"));
|
|
||||||
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
|
||||||
}
|
|
||||||
|
|
||||||
VBDEBUG(("EcUpdateImage() updating EC-%s...\n",
|
|
||||||
rw_request ? "RW" : "RO"));
|
|
||||||
|
|
||||||
if (shared->flags & VBSD_EC_SLOW_UPDATE) {
|
|
||||||
VBDEBUG(("EcUpdateImage() - EC is slow. Show WAIT screen.\n"));
|
|
||||||
|
|
||||||
/* Ensure the VGA Option ROM is loaded */
|
|
||||||
if ((shared->flags & VBSD_OPROM_MATTERS) &&
|
|
||||||
!(shared->flags & VBSD_OPROM_LOADED)) {
|
|
||||||
VBDEBUG(("EcUpdateImage() - Reboot to "
|
|
||||||
"load VGA Option ROM\n"));
|
|
||||||
VbNvSet(&vnc, VBNV_OPROM_NEEDED, 1);
|
|
||||||
return VBERROR_VGA_OPROM_MISMATCH;
|
|
||||||
}
|
|
||||||
|
|
||||||
VbDisplayScreen(cparams, VB_SCREEN_WAIT, 0, &vnc);
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = VbExEcUpdateImage(devidx, select, expected, expected_size);
|
|
||||||
if (rv != VBERROR_SUCCESS) {
|
|
||||||
VBDEBUG(("EcUpdateImage() - "
|
|
||||||
"VbExEcUpdateImage() returned %d\n", rv));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The EC may know it needs a reboot. It may need to
|
|
||||||
* unprotect the region before updating, or may need to
|
|
||||||
* reboot after updating. Either way, it's not an error
|
|
||||||
* requiring recovery mode.
|
|
||||||
*
|
|
||||||
* If we fail for any other reason, trigger recovery
|
|
||||||
* mode.
|
|
||||||
*/
|
|
||||||
if (rv != VBERROR_EC_REBOOT_TO_RO_REQUIRED)
|
|
||||||
VbSetRecoveryRequest(VBNV_RECOVERY_EC_UPDATE);
|
|
||||||
|
|
||||||
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Verify the EC was updated properly */
|
|
||||||
rv = VbExEcHashImage(devidx, select, &ec_hash, &ec_hash_size);
|
|
||||||
if (rv) {
|
|
||||||
VBDEBUG(("EcUpdateImage() - "
|
|
||||||
"VbExEcHashImage() returned %d\n", rv));
|
|
||||||
VbSetRecoveryRequest(VBNV_RECOVERY_EC_HASH_FAILED);
|
|
||||||
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
|
||||||
}
|
|
||||||
if (hash_size != ec_hash_size) {
|
|
||||||
VBDEBUG(("EcUpdateImage() - "
|
|
||||||
"VbExEcHashImage() says size %d, not %d\n",
|
|
||||||
ec_hash_size, hash_size));
|
|
||||||
VbSetRecoveryRequest(VBNV_RECOVERY_EC_HASH_SIZE);
|
|
||||||
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
|
||||||
}
|
|
||||||
VBDEBUG(("Updated EC-%s hash: ", rw_request ? "RW" : "RO"));
|
|
||||||
for (i = 0; i < ec_hash_size; i++)
|
|
||||||
VBDEBUG(("%02x",ec_hash[i]));
|
|
||||||
VBDEBUG(("\n"));
|
|
||||||
|
|
||||||
if (vb2_safe_memcmp(ec_hash, hash, hash_size)){
|
|
||||||
VBDEBUG(("EcUpdateImage() - "
|
|
||||||
"Failed to update EC-%s\n", rw_request ?
|
|
||||||
"RW" : "RO"));
|
|
||||||
VbSetRecoveryRequest(VBNV_RECOVERY_EC_UPDATE);
|
|
||||||
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
|
||||||
}
|
|
||||||
|
|
||||||
return VBERROR_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
VbError_t VbEcSoftwareSync(int devidx, VbCommonParams *cparams)
|
|
||||||
{
|
|
||||||
VbSharedDataHeader *shared =
|
|
||||||
(VbSharedDataHeader *)cparams->shared_data_blob;
|
|
||||||
enum VbSelectFirmware_t select_rw =
|
|
||||||
shared->firmware_index ? VB_SELECT_FIRMWARE_B :
|
|
||||||
VB_SELECT_FIRMWARE_A;
|
|
||||||
enum VbSelectFirmware_t select_ro = VB_SELECT_FIRMWARE_READONLY;
|
|
||||||
int in_rw = 0;
|
|
||||||
int ro_try_count = 2;
|
|
||||||
int num_tries = 0;
|
|
||||||
uint32_t try_ro_sync, recovery_request;
|
|
||||||
int rv, updated_rw, updated_ro;
|
|
||||||
|
|
||||||
VBDEBUG(("VbEcSoftwareSync(devidx=%d)\n", devidx));
|
|
||||||
|
|
||||||
/* Determine whether the EC is in RO or RW */
|
|
||||||
rv = VbExEcRunningRW(devidx, &in_rw);
|
|
||||||
|
|
||||||
if (shared->recovery_reason) {
|
|
||||||
/* Recovery mode; just verify the EC is in RO code */
|
|
||||||
if (rv == VBERROR_SUCCESS && in_rw == 1) {
|
|
||||||
/*
|
|
||||||
* EC is definitely in RW firmware. We want it in
|
|
||||||
* read-only code, so preserve the current recovery
|
|
||||||
* reason and reboot.
|
|
||||||
*
|
|
||||||
* We don't reboot on error or unknown EC code, because
|
|
||||||
* we could end up in an endless reboot loop. If we
|
|
||||||
* had some way to track that we'd already rebooted for
|
|
||||||
* this reason, we could retry only once.
|
|
||||||
*/
|
|
||||||
VBDEBUG(("VbEcSoftwareSync() - "
|
|
||||||
"want recovery but got EC-RW\n"));
|
|
||||||
VbSetRecoveryRequest(shared->recovery_reason);
|
|
||||||
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
|
||||||
}
|
|
||||||
|
|
||||||
VBDEBUG(("VbEcSoftwareSync() in recovery; EC-RO\n"));
|
|
||||||
return VBERROR_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Not in recovery. If we couldn't determine where the EC was,
|
|
||||||
* reboot to recovery.
|
|
||||||
*/
|
|
||||||
if (rv != VBERROR_SUCCESS) {
|
|
||||||
VBDEBUG(("VbEcSoftwareSync() - "
|
|
||||||
"VbExEcRunningRW() returned %d\n", rv));
|
|
||||||
VbSetRecoveryRequest(VBNV_RECOVERY_EC_UNKNOWN_IMAGE);
|
|
||||||
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If AP is read-only normal, EC should be in its RO code also. */
|
|
||||||
if (shared->flags & VBSD_LF_USE_RO_NORMAL) {
|
|
||||||
/* If EC is in RW code, request reboot back to RO */
|
|
||||||
if (in_rw == 1) {
|
|
||||||
VBDEBUG(("VbEcSoftwareSync() - "
|
|
||||||
"want RO-normal but got EC-RW\n"));
|
|
||||||
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Protect the RW flash and stay in EC-RO */
|
|
||||||
rv = EcProtect(devidx, select_rw);
|
|
||||||
if (rv != VBERROR_SUCCESS)
|
|
||||||
return rv;
|
|
||||||
|
|
||||||
rv = VbExEcDisableJump(devidx);
|
|
||||||
if (rv != VBERROR_SUCCESS) {
|
|
||||||
VBDEBUG(("VbEcSoftwareSync() - "
|
|
||||||
"VbExEcDisableJump() returned %d\n", rv));
|
|
||||||
VbSetRecoveryRequest(VBNV_RECOVERY_EC_SOFTWARE_SYNC);
|
|
||||||
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
|
||||||
}
|
|
||||||
|
|
||||||
VBDEBUG(("VbEcSoftwareSync() in RO-Normal; EC-RO\n"));
|
|
||||||
return VBERROR_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
VBDEBUG(("VbEcSoftwareSync() check for RW update.\n"));
|
|
||||||
|
|
||||||
/* Update the RW Image. */
|
|
||||||
rv = EcUpdateImage(devidx, cparams, select_rw, &updated_rw, in_rw);
|
|
||||||
|
|
||||||
if (rv != VBERROR_SUCCESS) {
|
|
||||||
VBDEBUG(("VbEcSoftwareSync() - "
|
|
||||||
"EcUpdateImage() returned %d\n", rv));
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tell EC to jump to its RW image */
|
|
||||||
if (!in_rw) {
|
|
||||||
VBDEBUG(("VbEcSoftwareSync() jumping to EC-RW\n"));
|
|
||||||
rv = VbExEcJumpToRW(devidx);
|
|
||||||
if (rv != VBERROR_SUCCESS) {
|
|
||||||
VBDEBUG(("VbEcSoftwareSync() - "
|
|
||||||
"VbExEcJumpToRW() returned %x\n", rv));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the EC booted RO-normal and a previous AP boot
|
|
||||||
* has called VbExEcStayInRO(), we need to reboot the EC
|
|
||||||
* to unlock the ability to jump to the RW firmware.
|
|
||||||
*
|
|
||||||
* All other errors trigger recovery mode.
|
|
||||||
*/
|
|
||||||
if (rv != VBERROR_EC_REBOOT_TO_RO_REQUIRED)
|
|
||||||
VbSetRecoveryRequest(VBNV_RECOVERY_EC_JUMP_RW);
|
|
||||||
|
|
||||||
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VbNvGet(&vnc, VBNV_TRY_RO_SYNC, &try_ro_sync);
|
|
||||||
|
|
||||||
if (!devidx && try_ro_sync &&
|
|
||||||
!(shared->flags & VBSD_BOOT_FIRMWARE_WP_ENABLED)) {
|
|
||||||
/* Reset RO Software Sync NV flag */
|
|
||||||
VbNvSet(&vnc, VBNV_TRY_RO_SYNC, 0);
|
|
||||||
|
|
||||||
VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &recovery_request);
|
|
||||||
|
|
||||||
/* Update the RO Image. */
|
|
||||||
while (num_tries < ro_try_count) {
|
|
||||||
VBDEBUG(("VbEcSoftwareSync() RO Software Sync\n"));
|
|
||||||
|
|
||||||
/* Get expected EC-RO Image. */
|
|
||||||
rv = EcUpdateImage(devidx, cparams, select_ro,
|
|
||||||
&updated_ro, in_rw);
|
|
||||||
if (rv == VBERROR_SUCCESS) {
|
|
||||||
/*
|
|
||||||
* If the RO update had failed, reset the
|
|
||||||
* recovery request.
|
|
||||||
*/
|
|
||||||
if (num_tries)
|
|
||||||
VbSetRecoveryRequest(recovery_request);
|
|
||||||
break;
|
|
||||||
} else
|
|
||||||
VBDEBUG(("VbEcSoftwareSync() - "
|
|
||||||
"EcUpdateImage() returned %d\n", rv));
|
|
||||||
|
|
||||||
num_tries++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (rv != VBERROR_SUCCESS)
|
|
||||||
return rv;
|
|
||||||
|
|
||||||
/* Protect RO flash */
|
|
||||||
rv = EcProtect(devidx, select_ro);
|
|
||||||
if (rv != VBERROR_SUCCESS)
|
|
||||||
return rv;
|
|
||||||
|
|
||||||
/* Protect RW flash */
|
|
||||||
rv = EcProtect(devidx, select_rw);
|
|
||||||
if (rv != VBERROR_SUCCESS)
|
|
||||||
return rv;
|
|
||||||
|
|
||||||
rv = VbExEcDisableJump(devidx);
|
|
||||||
if (rv != VBERROR_SUCCESS) {
|
|
||||||
VBDEBUG(("VbEcSoftwareSync() - "
|
|
||||||
"VbExEcDisableJump() returned %d\n", rv));
|
|
||||||
VbSetRecoveryRequest(VBNV_RECOVERY_EC_SOFTWARE_SYNC);
|
|
||||||
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reboot to unload VGA Option ROM if:
|
|
||||||
* - RW update was done
|
|
||||||
* - the system is NOT in developer mode
|
|
||||||
* - the system has slow EC update flag set
|
|
||||||
* - the VGA Option ROM was needed and loaded
|
|
||||||
*/
|
|
||||||
if (updated_rw &&
|
|
||||||
!(shared->flags & VBSD_BOOT_DEV_SWITCH_ON) &&
|
|
||||||
(shared->flags & VBSD_EC_SLOW_UPDATE) &&
|
|
||||||
(shared->flags & VBSD_OPROM_MATTERS) &&
|
|
||||||
(shared->flags & VBSD_OPROM_LOADED)) {
|
|
||||||
VBDEBUG(("VbEcSoftwareSync() - Reboot to "
|
|
||||||
"unload VGA Option ROM\n"));
|
|
||||||
VbNvSet(&vnc, VBNV_OPROM_NEEDED, 0);
|
|
||||||
return VBERROR_VGA_OPROM_MISMATCH;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This function is also used by tests */
|
/* This function is also used by tests */
|
||||||
void VbApiKernelFree(VbCommonParams *cparams)
|
void VbApiKernelFree(VbCommonParams *cparams)
|
||||||
{
|
{
|
||||||
@@ -1082,8 +727,7 @@ VbError_t VbSelectAndLoadKernel(VbCommonParams *cparams,
|
|||||||
/* Start timer */
|
/* Start timer */
|
||||||
shared->timer_vb_select_and_load_kernel_enter = VbExGetTimer();
|
shared->timer_vb_select_and_load_kernel_enter = VbExGetTimer();
|
||||||
|
|
||||||
VbExNvStorageRead(vnc.raw);
|
VbNvLoad();
|
||||||
VbNvSetup(&vnc);
|
|
||||||
|
|
||||||
/* Fill in params for calls to LoadKernel() */
|
/* Fill in params for calls to LoadKernel() */
|
||||||
memset(&p, 0, sizeof(p));
|
memset(&p, 0, sizeof(p));
|
||||||
@@ -1118,7 +762,7 @@ VbError_t VbSelectAndLoadKernel(VbCommonParams *cparams,
|
|||||||
!(cparams->gbb->flags & GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC)) {
|
!(cparams->gbb->flags & GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC)) {
|
||||||
int oprom_mismatch = 0;
|
int oprom_mismatch = 0;
|
||||||
|
|
||||||
retval = VbEcSoftwareSync(0, cparams);
|
retval = VbEcSoftwareSync(0, cparams, &vnc);
|
||||||
/* Save reboot requested until after possible PD sync */
|
/* Save reboot requested until after possible PD sync */
|
||||||
if (retval == VBERROR_VGA_OPROM_MISMATCH)
|
if (retval == VBERROR_VGA_OPROM_MISMATCH)
|
||||||
oprom_mismatch = 1;
|
oprom_mismatch = 1;
|
||||||
@@ -1128,7 +772,7 @@ VbError_t VbSelectAndLoadKernel(VbCommonParams *cparams,
|
|||||||
#ifdef PD_SYNC
|
#ifdef PD_SYNC
|
||||||
if (!(cparams->gbb->flags &
|
if (!(cparams->gbb->flags &
|
||||||
GBB_FLAG_DISABLE_PD_SOFTWARE_SYNC)) {
|
GBB_FLAG_DISABLE_PD_SOFTWARE_SYNC)) {
|
||||||
retval = VbEcSoftwareSync(1, cparams);
|
retval = VbEcSoftwareSync(1, cparams, &vnc);
|
||||||
if (retval == VBERROR_VGA_OPROM_MISMATCH)
|
if (retval == VBERROR_VGA_OPROM_MISMATCH)
|
||||||
oprom_mismatch = 1;
|
oprom_mismatch = 1;
|
||||||
else if (retval != VBERROR_SUCCESS)
|
else if (retval != VBERROR_SUCCESS)
|
||||||
@@ -1380,8 +1024,7 @@ VbError_t VbVerifyMemoryBootImage(VbCommonParams *cparams,
|
|||||||
*/
|
*/
|
||||||
dev_switch = shared->flags & VBSD_BOOT_DEV_SWITCH_ON;
|
dev_switch = shared->flags & VBSD_BOOT_DEV_SWITCH_ON;
|
||||||
|
|
||||||
VbExNvStorageRead(vnc.raw);
|
VbNvLoad();
|
||||||
VbNvSetup(&vnc);
|
|
||||||
VbNvGet(&vnc, VBNV_DEV_BOOT_FASTBOOT_FULL_CAP,
|
VbNvGet(&vnc, VBNV_DEV_BOOT_FASTBOOT_FULL_CAP,
|
||||||
&allow_fastboot_full_cap);
|
&allow_fastboot_full_cap);
|
||||||
|
|
||||||
@@ -1519,8 +1162,7 @@ VbError_t VbUnlockDevice(void)
|
|||||||
|
|
||||||
VbError_t VbLockDevice(void)
|
VbError_t VbLockDevice(void)
|
||||||
{
|
{
|
||||||
VbExNvStorageRead(vnc.raw);
|
VbNvLoad();
|
||||||
VbNvSetup(&vnc);
|
|
||||||
|
|
||||||
VBDEBUG(("%s() - Storing request to leave dev-mode.\n",
|
VBDEBUG(("%s() - Storing request to leave dev-mode.\n",
|
||||||
__func__));
|
__func__));
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ static int mock_ec_rw_hash_size;
|
|||||||
static uint8_t want_ec_hash[32];
|
static uint8_t want_ec_hash[32];
|
||||||
static uint8_t update_hash;
|
static uint8_t update_hash;
|
||||||
static int want_ec_hash_size;
|
static int want_ec_hash_size;
|
||||||
|
static VbNvContext mock_vnc;
|
||||||
|
|
||||||
static uint32_t screens_displayed[8];
|
static uint32_t screens_displayed[8];
|
||||||
static uint32_t screens_count = 0;
|
static uint32_t screens_count = 0;
|
||||||
@@ -64,13 +65,9 @@ static void ResetMocks(void)
|
|||||||
gbb.minor_version = GBB_MINOR_VER;
|
gbb.minor_version = GBB_MINOR_VER;
|
||||||
gbb.flags = 0;
|
gbb.flags = 0;
|
||||||
|
|
||||||
/*
|
memset(&mock_vnc, 0, sizeof(VbNvContext));
|
||||||
* Only the outermost vboot_api_kernel call sets vboot_api_kernel's
|
VbNvSetup(&mock_vnc);
|
||||||
* vnc. So clear it here too.
|
VbNvTeardown(&mock_vnc); /* So CRC gets generated */
|
||||||
*/
|
|
||||||
memset(VbApiKernelGetVnc(), 0, sizeof(VbNvContext));
|
|
||||||
VbNvSetup(VbApiKernelGetVnc());
|
|
||||||
VbNvTeardown(VbApiKernelGetVnc()); /* So CRC gets generated */
|
|
||||||
|
|
||||||
memset(&shared_data, 0, sizeof(shared_data));
|
memset(&shared_data, 0, sizeof(shared_data));
|
||||||
VbSharedDataInit(shared, sizeof(shared_data));
|
VbSharedDataInit(shared, sizeof(shared_data));
|
||||||
@@ -207,8 +204,8 @@ static void test_ssync(VbError_t retval, int recovery_reason, const char *desc)
|
|||||||
{
|
{
|
||||||
uint32_t u;
|
uint32_t u;
|
||||||
|
|
||||||
TEST_EQ(VbEcSoftwareSync(0, &cparams), retval, desc);
|
TEST_EQ(VbEcSoftwareSync(0, &cparams, &mock_vnc), retval, desc);
|
||||||
VbNvGet(VbApiKernelGetVnc(), VBNV_RECOVERY_REQUEST, &u);
|
VbNvGet(&mock_vnc, VBNV_RECOVERY_REQUEST, &u);
|
||||||
TEST_EQ(u, recovery_reason, " recovery reason");
|
TEST_EQ(u, recovery_reason, " recovery reason");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,7 +297,7 @@ static void VbSoftwareSyncTest(void)
|
|||||||
|
|
||||||
ResetMocks();
|
ResetMocks();
|
||||||
mock_ec_rw_hash[0]++;
|
mock_ec_rw_hash[0]++;
|
||||||
VbNvSet(VbApiKernelGetVnc(), VBNV_TRY_RO_SYNC, 1);
|
VbNvSet(&mock_vnc, VBNV_TRY_RO_SYNC, 1);
|
||||||
test_ssync(0, 0, "Update rw without reboot");
|
test_ssync(0, 0, "Update rw without reboot");
|
||||||
TEST_EQ(ec_rw_protected, 1, " ec rw protected");
|
TEST_EQ(ec_rw_protected, 1, " ec rw protected");
|
||||||
TEST_EQ(ec_run_image, 1, " ec run image");
|
TEST_EQ(ec_run_image, 1, " ec run image");
|
||||||
@@ -311,7 +308,7 @@ static void VbSoftwareSyncTest(void)
|
|||||||
ResetMocks();
|
ResetMocks();
|
||||||
mock_ec_rw_hash[0]++;
|
mock_ec_rw_hash[0]++;
|
||||||
mock_ec_ro_hash[0]++;
|
mock_ec_ro_hash[0]++;
|
||||||
VbNvSet(VbApiKernelGetVnc(), VBNV_TRY_RO_SYNC, 1);
|
VbNvSet(&mock_vnc, VBNV_TRY_RO_SYNC, 1);
|
||||||
test_ssync(0, 0, "Update rw and ro images without reboot");
|
test_ssync(0, 0, "Update rw and ro images without reboot");
|
||||||
TEST_EQ(ec_rw_protected, 1, " ec rw protected");
|
TEST_EQ(ec_rw_protected, 1, " ec rw protected");
|
||||||
TEST_EQ(ec_run_image, 1, " ec run image");
|
TEST_EQ(ec_run_image, 1, " ec run image");
|
||||||
@@ -321,7 +318,7 @@ static void VbSoftwareSyncTest(void)
|
|||||||
|
|
||||||
ResetMocks();
|
ResetMocks();
|
||||||
shared->flags |= VBSD_BOOT_FIRMWARE_WP_ENABLED;
|
shared->flags |= VBSD_BOOT_FIRMWARE_WP_ENABLED;
|
||||||
VbNvSet(VbApiKernelGetVnc(), VBNV_TRY_RO_SYNC, 1);
|
VbNvSet(&mock_vnc, VBNV_TRY_RO_SYNC, 1);
|
||||||
mock_ec_rw_hash[0]++;
|
mock_ec_rw_hash[0]++;
|
||||||
mock_ec_ro_hash[0]++;
|
mock_ec_ro_hash[0]++;
|
||||||
test_ssync(0, 0, "WP enabled");
|
test_ssync(0, 0, "WP enabled");
|
||||||
@@ -332,7 +329,7 @@ static void VbSoftwareSyncTest(void)
|
|||||||
TEST_EQ(ec_ro_updated, 0, " ec ro updated");
|
TEST_EQ(ec_ro_updated, 0, " ec ro updated");
|
||||||
|
|
||||||
ResetMocks();
|
ResetMocks();
|
||||||
VbNvSet(VbApiKernelGetVnc(), VBNV_TRY_RO_SYNC, 1);
|
VbNvSet(&mock_vnc, VBNV_TRY_RO_SYNC, 1);
|
||||||
mock_ec_ro_hash[0]++;
|
mock_ec_ro_hash[0]++;
|
||||||
test_ssync(0, 0, "rw update not needed");
|
test_ssync(0, 0, "rw update not needed");
|
||||||
TEST_EQ(ec_rw_protected, 1, " ec rw protected");
|
TEST_EQ(ec_rw_protected, 1, " ec rw protected");
|
||||||
@@ -81,7 +81,8 @@ VbError_t VbExNvStorageWrite(const uint8_t *buf)
|
|||||||
return VBERROR_SUCCESS;
|
return VBERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
VbError_t VbEcSoftwareSync(int devidx, VbCommonParams *cparams)
|
VbError_t VbEcSoftwareSync(int devidx, VbCommonParams *cparams,
|
||||||
|
VbNvContext *vnc)
|
||||||
{
|
{
|
||||||
return ecsync_retval;
|
return ecsync_retval;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user