mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-11 02:15:14 +00:00
EFS: Add support for early firmware selection
Chromebox ECs performs EFS: verifying firmware before the AP boots. This patch updates host commands which are required for the EFS. The change includes: * Update EC_CMD_FLASH_REGION_INFO to accept EC_FLASH_REGION_UPDATE * Update EC_CMD_VBOOT_HASH to accept EC_VBOOT_HASH_OFFSET_UPDATE When EC_FLASHS_REGION_UPDATE is specified, EC_CMD_FLASH_REGION_INFO returns the slot which currently is not hosting a running RW copy. When EC_VBOOT_HASH_OFFSET_UPDATE is specified, EC_CMD_VBOOT_HASH computs the hash of the update slot. This hash covers the entire region, including the signature at the end. This patch undefines CONFIG_CMD_USBMUX and CONFIG_CMD_TYPEC for gru to create space. BUG=b:65028930 BRANCH=none CQ-DEPEND=CL:648071 TEST=On Fizz, verify: 1. RW_B is old and updated by soft sync. RW_B is activated and executed after reboot. System continues to boot to OS. 2. RW_A is old and updated by soft sync. RW_A is activated and executed after reboot. System continues to boot to OS. Change-Id: I9ece907b764d07ce94054ba27996e048c665a80a Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/648448
This commit is contained in:
committed by
chrome-bot
parent
a52cfbc80c
commit
4dcee1c545
@@ -205,6 +205,8 @@
|
||||
#undef CONFIG_CMD_ACCELSPOOF
|
||||
#undef CONFIG_CMD_I2C_XFER
|
||||
#undef CONFIG_CMD_SHMEM
|
||||
#undef CONFIG_CMD_USBMUX
|
||||
#undef CONFIG_CMD_TYPEC
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
@@ -1286,6 +1286,28 @@ static int flash_command_protect(struct host_cmd_handler_args *args)
|
||||
return EC_RES_SUCCESS;
|
||||
}
|
||||
|
||||
enum flash_rw_slot flash_get_active_slot(void)
|
||||
{
|
||||
uint8_t slot;
|
||||
if (system_get_bbram(SYSTEM_BBRAM_IDX_TRY_SLOT, &slot))
|
||||
slot = FLASH_RW_SLOT_A;
|
||||
return slot;
|
||||
}
|
||||
|
||||
enum flash_rw_slot flash_get_update_slot(void)
|
||||
{
|
||||
#ifdef CONFIG_VBOOT_EFS
|
||||
return 1 - flash_get_active_slot();
|
||||
#else
|
||||
return FLASH_RW_SLOT_A;
|
||||
#endif
|
||||
}
|
||||
|
||||
enum system_image_copy_t flash_slot_to_image(enum flash_rw_slot slot)
|
||||
{
|
||||
return slot == FLASH_RW_SLOT_A ? SYSTEM_IMAGE_RW_A : SYSTEM_IMAGE_RW_B;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO(crbug.com/239197) : Adding both versions to the version mask is a
|
||||
* temporary workaround for a problem in the cros_ec driver. Drop
|
||||
@@ -1307,10 +1329,9 @@ static int flash_command_region_info(struct host_cmd_handler_args *args)
|
||||
EC_FLASH_REGION_START;
|
||||
r->size = CONFIG_RO_SIZE;
|
||||
break;
|
||||
case EC_FLASH_REGION_RW:
|
||||
r->offset = CONFIG_EC_WRITABLE_STORAGE_OFF +
|
||||
CONFIG_RW_STORAGE_OFF -
|
||||
EC_FLASH_REGION_START;
|
||||
case EC_FLASH_REGION_ACTIVE:
|
||||
r->offset = flash_get_rw_offset(flash_get_active_slot()) -
|
||||
EC_FLASH_REGION_START;
|
||||
r->size = CONFIG_RW_SIZE;
|
||||
break;
|
||||
case EC_FLASH_REGION_WP_RO:
|
||||
@@ -1318,6 +1339,11 @@ static int flash_command_region_info(struct host_cmd_handler_args *args)
|
||||
EC_FLASH_REGION_START;
|
||||
r->size = CONFIG_WP_STORAGE_SIZE;
|
||||
break;
|
||||
case EC_FLASH_REGION_UPDATE:
|
||||
r->offset = flash_get_rw_offset(flash_get_update_slot()) -
|
||||
EC_FLASH_REGION_START;
|
||||
r->size = CONFIG_RW_SIZE;
|
||||
break;
|
||||
default:
|
||||
return EC_RES_INVALID_PARAM;
|
||||
}
|
||||
|
||||
@@ -420,14 +420,19 @@ test_mockable int system_unsafe_to_overwrite(uint32_t offset, uint32_t size)
|
||||
r_size = CONFIG_RO_SIZE;
|
||||
break;
|
||||
case SYSTEM_IMAGE_RW:
|
||||
r_offset = CONFIG_EC_WRITABLE_STORAGE_OFF +
|
||||
CONFIG_RW_STORAGE_OFF;
|
||||
r_offset = flash_get_rw_offset(FLASH_RW_SLOT_A);
|
||||
r_size = CONFIG_RW_SIZE;
|
||||
#ifdef CONFIG_RWSIG
|
||||
/* Allow RW sig to be overwritten */
|
||||
r_size -= CONFIG_RW_SIG_SIZE;
|
||||
#endif
|
||||
break;
|
||||
#ifdef CONFIG_VBOOT_EFS
|
||||
case SYSTEM_IMAGE_RW_B:
|
||||
r_offset = flash_get_rw_offset(FLASH_RW_SLOT_B);
|
||||
r_size = CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -614,6 +619,19 @@ int system_run_image_copy(enum system_image_copy_t copy)
|
||||
return EC_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is defined in system.c instead of flash.c because it's called even
|
||||
* on the boards which don't include flash.o. (e.g. hadoken, stm32l476g-eval)
|
||||
*/
|
||||
uint32_t flash_get_rw_offset(enum flash_rw_slot slot)
|
||||
{
|
||||
#ifdef CONFIG_VBOOT_EFS
|
||||
if (slot == FLASH_RW_SLOT_B)
|
||||
return CONFIG_EC_WRITABLE_STORAGE_OFF + CONFIG_RW_B_STORAGE_OFF;
|
||||
#endif
|
||||
return CONFIG_EC_WRITABLE_STORAGE_OFF + CONFIG_RW_STORAGE_OFF;
|
||||
}
|
||||
|
||||
static const struct image_data *system_get_image_data(
|
||||
enum system_image_copy_t copy)
|
||||
{
|
||||
@@ -639,9 +657,17 @@ static const struct image_data *system_get_image_data(
|
||||
* Read the version information from the proper location
|
||||
* on storage.
|
||||
*/
|
||||
addr += (is_rw_image(copy)) ?
|
||||
CONFIG_EC_WRITABLE_STORAGE_OFF + CONFIG_RW_STORAGE_OFF :
|
||||
CONFIG_EC_PROTECTED_STORAGE_OFF + CONFIG_RO_STORAGE_OFF;
|
||||
switch (copy) {
|
||||
case SYSTEM_IMAGE_RW:
|
||||
addr += flash_get_rw_offset(FLASH_RW_SLOT_A);
|
||||
break;
|
||||
case SYSTEM_IMAGE_RW_B:
|
||||
addr += flash_get_rw_offset(FLASH_RW_SLOT_B);
|
||||
break;
|
||||
default:
|
||||
addr += CONFIG_EC_PROTECTED_STORAGE_OFF + CONFIG_RO_STORAGE_OFF;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MAPPED_STORAGE
|
||||
addr += CONFIG_MAPPED_STORAGE_BASE;
|
||||
@@ -1198,10 +1224,12 @@ DECLARE_CONSOLE_COMMAND(sysrq, command_sysrq,
|
||||
static int host_command_get_version(struct host_cmd_handler_args *args)
|
||||
{
|
||||
struct ec_response_get_version *r = args->response;
|
||||
enum flash_rw_slot active_slot = flash_get_active_slot();
|
||||
|
||||
strzcpy(r->version_string_ro, system_get_version(SYSTEM_IMAGE_RO),
|
||||
sizeof(r->version_string_ro));
|
||||
strzcpy(r->version_string_rw, system_get_version(SYSTEM_IMAGE_RW),
|
||||
strzcpy(r->version_string_rw,
|
||||
system_get_version(flash_slot_to_image(active_slot)),
|
||||
sizeof(r->version_string_rw));
|
||||
|
||||
switch (system_get_image_copy()) {
|
||||
@@ -1209,6 +1237,7 @@ static int host_command_get_version(struct host_cmd_handler_args *args)
|
||||
r->current_image = EC_IMAGE_RO;
|
||||
break;
|
||||
case SYSTEM_IMAGE_RW:
|
||||
case SYSTEM_IMAGE_RW_B:
|
||||
r->current_image = EC_IMAGE_RW;
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -219,6 +219,18 @@ int vboot_hash_invalidate(int offset, int size)
|
||||
/*****************************************************************************/
|
||||
/* Hooks */
|
||||
|
||||
/**
|
||||
* Returns the size of a RW copy to be hashed as expected by Softsync.
|
||||
*/
|
||||
static uint32_t get_rw_size(void)
|
||||
{
|
||||
#ifdef CONFIG_VBOOT_EFS
|
||||
return CONFIG_RW_SIZE;
|
||||
#else
|
||||
return system_get_image_used(SYSTEM_IMAGE_RW);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void vboot_hash_init(void)
|
||||
{
|
||||
#ifdef CONFIG_SAVE_VBOOT_HASH
|
||||
@@ -249,10 +261,8 @@ static void vboot_hash_init(void)
|
||||
#endif
|
||||
{
|
||||
/* Start computing the hash of RW firmware */
|
||||
vboot_hash_start(CONFIG_EC_WRITABLE_STORAGE_OFF +
|
||||
CONFIG_RW_STORAGE_OFF,
|
||||
system_get_image_used(SYSTEM_IMAGE_RW),
|
||||
NULL, 0);
|
||||
vboot_hash_start(flash_get_rw_offset(flash_get_active_slot()),
|
||||
get_rw_size(), NULL, 0);
|
||||
}
|
||||
}
|
||||
DECLARE_HOOK(HOOK_INIT, vboot_hash_init, HOOK_PRIO_INIT_VBOOT_HASH);
|
||||
@@ -279,6 +289,21 @@ DECLARE_HOOK(HOOK_SYSJUMP, vboot_hash_preserve_state, HOOK_PRIO_DEFAULT);
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns the offset of RO or RW image if the either region is specifically
|
||||
* requested otherwise return the current hash offset.
|
||||
*/
|
||||
static int get_offset(int offset)
|
||||
{
|
||||
if (offset == EC_VBOOT_HASH_OFFSET_RO)
|
||||
return CONFIG_EC_PROTECTED_STORAGE_OFF + CONFIG_RO_STORAGE_OFF;
|
||||
if (offset == EC_VBOOT_HASH_OFFSET_ACTIVE)
|
||||
return flash_get_rw_offset(flash_get_active_slot());
|
||||
if (offset == EC_VBOOT_HASH_OFFSET_UPDATE)
|
||||
return flash_get_rw_offset(flash_get_update_slot());
|
||||
return offset;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* Console commands */
|
||||
#ifdef CONFIG_CMD_HASH
|
||||
@@ -311,10 +336,8 @@ static int command_hash(int argc, char **argv)
|
||||
return EC_SUCCESS;
|
||||
} else if (!strcasecmp(argv[1], "rw")) {
|
||||
return vboot_hash_start(
|
||||
CONFIG_EC_WRITABLE_STORAGE_OFF +
|
||||
CONFIG_RW_STORAGE_OFF,
|
||||
system_get_image_used(SYSTEM_IMAGE_RW),
|
||||
NULL, 0);
|
||||
get_offset(EC_VBOOT_HASH_OFFSET_ACTIVE),
|
||||
get_rw_size(), NULL, 0);
|
||||
} else if (!strcasecmp(argv[1], "ro")) {
|
||||
return vboot_hash_start(
|
||||
CONFIG_EC_PROTECTED_STORAGE_OFF +
|
||||
@@ -352,19 +375,6 @@ DECLARE_CONSOLE_COMMAND(hash, command_hash,
|
||||
/****************************************************************************/
|
||||
/* Host commands */
|
||||
|
||||
/**
|
||||
* Return the offset of the RO or RW region if the either region is specifically
|
||||
* requested otherwise return the current hash offset.
|
||||
*/
|
||||
static int get_offset(int offset)
|
||||
{
|
||||
if (offset == EC_VBOOT_HASH_OFFSET_RO)
|
||||
return CONFIG_EC_PROTECTED_STORAGE_OFF + CONFIG_RO_STORAGE_OFF;
|
||||
if (offset == EC_VBOOT_HASH_OFFSET_RW)
|
||||
return CONFIG_EC_WRITABLE_STORAGE_OFF + CONFIG_RW_STORAGE_OFF;
|
||||
return data_offset;
|
||||
}
|
||||
|
||||
/* Fill in the response with the current hash status */
|
||||
static void fill_response(struct ec_response_vboot_hash *r,
|
||||
int request_offset)
|
||||
@@ -403,14 +413,12 @@ static int host_start_hash(const struct ec_params_vboot_hash *p)
|
||||
return EC_RES_INVALID_PARAM;
|
||||
|
||||
/* Handle special offset values */
|
||||
if (offset == EC_VBOOT_HASH_OFFSET_RO) {
|
||||
offset = CONFIG_EC_PROTECTED_STORAGE_OFF +
|
||||
CONFIG_RO_STORAGE_OFF;
|
||||
if (offset == EC_VBOOT_HASH_OFFSET_RO)
|
||||
size = system_get_image_used(SYSTEM_IMAGE_RO);
|
||||
} else if (p->offset == EC_VBOOT_HASH_OFFSET_RW) {
|
||||
offset = CONFIG_EC_WRITABLE_STORAGE_OFF + CONFIG_RW_STORAGE_OFF;
|
||||
size = system_get_image_used(SYSTEM_IMAGE_RW);
|
||||
}
|
||||
else if ((offset == EC_VBOOT_HASH_OFFSET_ACTIVE) ||
|
||||
(offset == EC_VBOOT_HASH_OFFSET_UPDATE))
|
||||
size = get_rw_size();
|
||||
offset = get_offset(offset);
|
||||
rv = vboot_hash_start(offset, size, p->nonce_data, p->nonce_size);
|
||||
|
||||
if (rv == EC_SUCCESS)
|
||||
|
||||
@@ -1381,16 +1381,29 @@ struct __ec_align4 ec_response_flash_protect {
|
||||
enum ec_flash_region {
|
||||
/* Region which holds read-only EC image */
|
||||
EC_FLASH_REGION_RO = 0,
|
||||
/* Region which holds rewritable EC image */
|
||||
EC_FLASH_REGION_RW,
|
||||
/*
|
||||
* Region which holds active RW image. 'Active' is different from
|
||||
* 'running'. Active means 'scheduled-to-run'. Since RO image always
|
||||
* scheduled to run, active/non-active applies only to RW images (for
|
||||
* the same reason 'update' applies only to RW images. It's a state of
|
||||
* an image on a flash. Running image can be RO, RW_A, RW_B but active
|
||||
* image can only be RW_A or RW_B. In recovery mode, an active RW image
|
||||
* doesn't enter 'running' state but it's still active on a flash.
|
||||
*/
|
||||
EC_FLASH_REGION_ACTIVE,
|
||||
/*
|
||||
* Region which should be write-protected in the factory (a superset of
|
||||
* EC_FLASH_REGION_RO)
|
||||
*/
|
||||
EC_FLASH_REGION_WP_RO,
|
||||
/* Region which holds updatable (non-active) RW image */
|
||||
EC_FLASH_REGION_UPDATE,
|
||||
/* Number of regions */
|
||||
EC_FLASH_REGION_COUNT,
|
||||
};
|
||||
/* 'RW' is vague if there are multiple RW images; we mean the active one,
|
||||
* so the old constant is deprecated */
|
||||
#define EC_FLASH_REGION_RW EC_FLASH_REGION_ACTIVE
|
||||
|
||||
struct __ec_align4 ec_params_flash_region_info {
|
||||
uint32_t region; /* enum ec_flash_region */
|
||||
@@ -1951,8 +1964,13 @@ enum ec_vboot_hash_status {
|
||||
* If one of these is specified, the EC will automatically update offset and
|
||||
* size to the correct values for the specified image (RO or RW).
|
||||
*/
|
||||
#define EC_VBOOT_HASH_OFFSET_RO 0xfffffffe
|
||||
#define EC_VBOOT_HASH_OFFSET_RW 0xfffffffd
|
||||
#define EC_VBOOT_HASH_OFFSET_RO 0xfffffffe
|
||||
#define EC_VBOOT_HASH_OFFSET_ACTIVE 0xfffffffd
|
||||
#define EC_VBOOT_HASH_OFFSET_UPDATE 0xfffffffc
|
||||
|
||||
/* 'RW' is vague if there are multiple RW images; we mean the active one,
|
||||
* so the old constant is deprecated */
|
||||
#define EC_VBOOT_HASH_OFFSET_RW EC_VBOOT_HASH_OFFSET_ACTIVE
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
|
||||
@@ -102,6 +102,31 @@ enum flash_region {
|
||||
FLASH_REGION_COUNT
|
||||
};
|
||||
|
||||
/**
|
||||
* Get active slot
|
||||
*
|
||||
* Active slot contains an image which is being executed or will be executed
|
||||
* after sysjump.
|
||||
*
|
||||
* @return Active slot index
|
||||
*/
|
||||
enum flash_rw_slot flash_get_active_slot(void);
|
||||
|
||||
/**
|
||||
* Get updatable (non-active) slot
|
||||
*
|
||||
* @return Updatable slot index
|
||||
*/
|
||||
enum flash_rw_slot flash_get_update_slot(void);
|
||||
|
||||
/**
|
||||
* Translate slot index to image index
|
||||
*
|
||||
* @param slot Slot index to convert.
|
||||
* @return Image index converted from <slot>
|
||||
*/
|
||||
enum system_image_copy_t flash_slot_to_image(enum flash_rw_slot slot);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Low-level methods, for use by flash_common. */
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ enum system_image_copy_t {
|
||||
SYSTEM_IMAGE_UNKNOWN = 0,
|
||||
SYSTEM_IMAGE_RO,
|
||||
SYSTEM_IMAGE_RW,
|
||||
SYSTEM_IMAGE_RW_A = SYSTEM_IMAGE_RW,
|
||||
/* Some systems may have these too */
|
||||
SYSTEM_IMAGE_RO_B,
|
||||
SYSTEM_IMAGE_RW_B,
|
||||
@@ -561,4 +562,18 @@ static inline void system_print_extended_version_info(void)
|
||||
*/
|
||||
int system_can_boot_ap(void);
|
||||
|
||||
enum flash_rw_slot {
|
||||
/* Must be 0 and 1 because they are converted by 1 - slot_x. */
|
||||
FLASH_RW_SLOT_A = 0,
|
||||
FLASH_RW_SLOT_B = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* Get flash offset of a RW slot
|
||||
*
|
||||
* @param slot Slot index to get the flash offset of.
|
||||
* @return Flash offset of the slot specified by <slot>
|
||||
*/
|
||||
uint32_t flash_get_rw_offset(enum flash_rw_slot slot);
|
||||
|
||||
#endif /* __CROS_EC_SYSTEM_H */
|
||||
|
||||
@@ -364,11 +364,14 @@ static int test_region_info(void)
|
||||
VERIFY_REGION_INFO(EC_FLASH_REGION_RO,
|
||||
CONFIG_EC_PROTECTED_STORAGE_OFF +
|
||||
CONFIG_RO_STORAGE_OFF, CONFIG_RO_SIZE);
|
||||
VERIFY_REGION_INFO(EC_FLASH_REGION_RW,
|
||||
VERIFY_REGION_INFO(EC_FLASH_REGION_ACTIVE,
|
||||
CONFIG_EC_WRITABLE_STORAGE_OFF +
|
||||
CONFIG_RW_STORAGE_OFF, CONFIG_RW_SIZE);
|
||||
VERIFY_REGION_INFO(EC_FLASH_REGION_WP_RO,
|
||||
CONFIG_WP_STORAGE_OFF, CONFIG_WP_STORAGE_SIZE);
|
||||
VERIFY_REGION_INFO(EC_FLASH_REGION_UPDATE,
|
||||
CONFIG_EC_WRITABLE_STORAGE_OFF +
|
||||
CONFIG_RW_STORAGE_OFF, CONFIG_RW_SIZE);
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -6232,7 +6232,7 @@ int cmd_ec_hash(int argc, char *argv[])
|
||||
p.size = 0;
|
||||
printf("Hashing EC-RO...\n");
|
||||
} else if (!strcasecmp(argv[2], "rw")) {
|
||||
p.offset = EC_VBOOT_HASH_OFFSET_RW;
|
||||
p.offset = EC_VBOOT_HASH_OFFSET_ACTIVE;
|
||||
p.size = 0;
|
||||
printf("Hashing EC-RW...\n");
|
||||
} else if (argc < 4) {
|
||||
|
||||
Reference in New Issue
Block a user