summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaisuke Nojiri <dnojiri@chromium.org>2017-08-15 16:34:52 -0700
committerchrome-bot <chrome-bot@chromium.org>2017-09-12 01:11:59 -0700
commit4dcee1c545c31d288b23221d8e07bc452214ce7b (patch)
tree1ddab11d51dcd5c0571f6f777b655ba333cd84e6
parenta52cfbc80c060d9883aee9de4e764e0b250d184a (diff)
downloadchrome-ec-4dcee1c545c31d288b23221d8e07bc452214ce7b.tar.gz
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
-rw-r--r--board/kevin/board.h2
-rw-r--r--common/flash.c34
-rw-r--r--common/system.c41
-rw-r--r--common/vboot_hash.c64
-rw-r--r--include/ec_commands.h26
-rw-r--r--include/flash.h25
-rw-r--r--include/system.h15
-rw-r--r--test/flash.c5
-rw-r--r--util/ectool.c2
9 files changed, 170 insertions, 44 deletions
diff --git a/board/kevin/board.h b/board/kevin/board.h
index bc07195d64..1f49105386 100644
--- a/board/kevin/board.h
+++ b/board/kevin/board.h
@@ -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
/*
diff --git a/common/flash.c b/common/flash.c
index 36c4701264..3d6f579834 100644
--- a/common/flash.c
+++ b/common/flash.c
@@ -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;
}
diff --git a/common/system.c b/common/system.c
index 07d43da38b..62c036baf9 100644
--- a/common/system.c
+++ b/common/system.c
@@ -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:
diff --git a/common/vboot_hash.c b/common/vboot_hash.c
index 81d60725aa..fab56c1d0a 100644
--- a/common/vboot_hash.c
+++ b/common/vboot_hash.c
@@ -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)
diff --git a/include/ec_commands.h b/include/ec_commands.h
index 223a25fcbe..3eab0a8354 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -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
/*****************************************************************************/
/*
diff --git a/include/flash.h b/include/flash.h
index c769f5753d..d52f1f7ce7 100644
--- a/include/flash.h
+++ b/include/flash.h
@@ -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. */
diff --git a/include/system.h b/include/system.h
index 2a229a68ef..d44cb315b1 100644
--- a/include/system.h
+++ b/include/system.h
@@ -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 */
diff --git a/test/flash.c b/test/flash.c
index b3bad5e984..3ee3384619 100644
--- a/test/flash.c
+++ b/test/flash.c
@@ -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;
}
diff --git a/util/ectool.c b/util/ectool.c
index 449e4ec818..89b3b6e028 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -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) {