summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Boichat <drinkcat@google.com>2017-04-12 17:41:13 +0800
committerchrome-bot <chrome-bot@chromium.org>2017-04-21 06:03:58 -0700
commitcca405862ad3d4df1d1382561e7c8d3e383a8338 (patch)
tree9d8fe84260b20e25900538f78784fb1cf26cee0a
parent30bd74b23314f6cd75e1153e3e7be5e19252537f (diff)
downloadchrome-ec-cca405862ad3d4df1d1382561e7c8d3e383a8338.tar.gz
common/update_fw: Board/chip-specific first_response_pdu
cr50 and hammer/common code are such different chips that reusing the same first_response_pdu does not make much sense. Instead, we can use 2 different headers, the updater knows which response to expect based on USB product ID. In the common code answer, we can reply with the EC version string, as well as rollback information and key version ID, which will be required for reliable updating. BRANCH=none BUG=b:35587171 BUG=b:36375666 TEST=usb_updater2 can update hammer, and read its version, rollback version and key version. Change-Id: I20b04070606767c71df3e6286d53e238e13375c0 Reviewed-on: https://chromium-review.googlesource.com/476452 Commit-Ready: Nicolas Boichat <drinkcat@chromium.org> Tested-by: Nicolas Boichat <drinkcat@chromium.org> Reviewed-by: Nick Sanders <nsanders@chromium.org> Reviewed-by: Nicolas Boichat <drinkcat@chromium.org>
-rw-r--r--common/update_fw.c57
-rw-r--r--include/update_fw.h62
2 files changed, 85 insertions, 34 deletions
diff --git a/common/update_fw.c b/common/update_fw.c
index 8135370b7c..7a51e6977f 100644
--- a/common/update_fw.c
+++ b/common/update_fw.c
@@ -9,10 +9,13 @@
#include "flash.h"
#include "hooks.h"
#include "include/compile_time_macros.h"
+#include "rollback.h"
+#include "rwsig.h"
#include "system.h"
#include "uart.h"
#include "update_fw.h"
#include "util.h"
+#include "vb21_struct.h"
#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args)
@@ -98,17 +101,26 @@ static int contents_allowed(uint32_t block_offset,
*/
void fw_update_start(struct first_response_pdu *rpdu)
{
+ const char *version;
+#ifdef CONFIG_RWSIG_TYPE_RWSIG
+ const struct vb21_packed_key *vb21_key;
+#endif
+
+ rpdu->header_type = htobe16(UPDATE_HEADER_TYPE_COMMON);
+
/* Determine the valid update section. */
switch (system_get_image_copy()) {
case SYSTEM_IMAGE_RO:
/* RO running, so update RW */
update_section.base_offset = CONFIG_RW_MEM_OFF;
update_section.top_offset = CONFIG_RW_MEM_OFF + CONFIG_RW_SIZE;
+ version = system_get_version(SYSTEM_IMAGE_RW);
break;
case SYSTEM_IMAGE_RW:
/* RW running, so update RO */
update_section.base_offset = CONFIG_RO_MEM_OFF;
update_section.top_offset = CONFIG_RO_MEM_OFF + CONFIG_RO_SIZE;
+ version = system_get_version(SYSTEM_IMAGE_RO);
break;
default:
CPRINTF("%s:%d\n", __func__, __LINE__);
@@ -116,27 +128,23 @@ void fw_update_start(struct first_response_pdu *rpdu)
return;
}
- /*
- * TODO(b/36375666): We reuse the same structure as cr50 updater, but
- * there isn't a whole lot that can be shared... We should probably
- * switch to a board-specific response packet (at least common vs
- * cr50-specific).
- */
- rpdu->backup_ro_offset = htobe32(update_section.base_offset);
- rpdu->backup_rw_offset = 0x0;
-
- /* RO header information. */
- rpdu->shv[0].minor = 0;
- rpdu->shv[0].major = 0;
- rpdu->shv[0].epoch = 0;
- rpdu->keyid[0] = 0;
-
- /* RW header information. */
- rpdu->shv[1].minor = 0;
- rpdu->shv[1].major = 0;
- rpdu->shv[1].epoch = 0;
-
- rpdu->keyid[1] = 0;
+ rpdu->common.maximum_pdu_size = htobe32(CONFIG_UPDATE_PDU_SIZE);
+ rpdu->common.flash_protection = htobe32(flash_get_protect());
+ rpdu->common.offset = htobe32(update_section.base_offset);
+ if (version)
+ memcpy(rpdu->common.version, version,
+ sizeof(rpdu->common.version));
+
+#ifdef CONFIG_ROLLBACK
+ rpdu->common.min_rollback = htobe32(rollback_get_minimum_version());
+#else
+ rpdu->common.min_rollback = htobe32(-1);
+#endif
+
+#ifdef CONFIG_RWSIG_TYPE_RWSIG
+ vb21_key = (const struct vb21_packed_key *)CONFIG_RO_PUBKEY_ADDR;
+ rpdu->common.key_version = htobe32(vb21_key->key_version);
+#endif
}
void fw_update_command_handler(void *body,
@@ -169,8 +177,13 @@ void fw_update_command_handler(void *body,
/* First, prepare the response structure. */
memset(rpdu, 0, sizeof(*rpdu));
+ /*
+ * TODO(b/36375666): The response size can be shorter depending
+ * on which board-specific type of response we provide. This
+ * may send trailing 0 bytes, which should be harmless.
+ */
*response_size = sizeof(*rpdu);
- rpdu->protocol_version = htobe32(UPDATE_PROTOCOL_VERSION);
+ rpdu->protocol_version = htobe16(UPDATE_PROTOCOL_VERSION);
/* Setup internal state (e.g. valid sections, and fill rpdu) */
fw_update_start(rpdu);
diff --git a/include/update_fw.h b/include/update_fw.h
index dd8b7c1a04..115b34d35c 100644
--- a/include/update_fw.h
+++ b/include/update_fw.h
@@ -64,7 +64,7 @@ struct update_frame_header {
/*
* A convenience structure which allows to group together various revision
- * fields of the header created by the signer.
+ * fields of the header created by the signer (cr50-specific).
*
* These fields are compared when deciding if versions of two images are the
* same or when deciding which one of the available images to run.
@@ -99,19 +99,57 @@ struct first_response_pdu {
uint32_t return_value;
/* The below fields are present in versions 2 and up. */
- uint32_t protocol_version;
- /* The below fields are present in versions 3 and up. */
- uint32_t backup_ro_offset;
- uint32_t backup_rw_offset;
-
- /* The below fields are present in versions 4 and up. */
- /* Versions of the currently active RO and RW sections. */
- struct signed_header_version shv[2];
+ /* Type of header following (one of first_response_pdu_header_type) */
+ uint16_t header_type;
+
+ /* Must be UPDATE_PROTOCOL_VERSION */
+ uint16_t protocol_version;
+
+ /* In version 6 and up, a board-specific header follows. */
+ union {
+ /* cr50 (header_type = UPDATE_HEADER_TYPE_CR50) */
+ struct {
+ /* The below fields are present in versions 3 and up. */
+ uint32_t backup_ro_offset;
+ uint32_t backup_rw_offset;
+
+ /* The below fields are present in versions 4 and up. */
+ /*
+ * Versions of the currently active RO and RW sections.
+ */
+ struct signed_header_version shv[2];
+
+ /* The below fields are present in versions 5 and up */
+ /* keyids of the currently active RO and RW sections. */
+ uint32_t keyid[2];
+ } cr50;
+ /* Common code (header_type = UPDATE_HEADER_TYPE_COMMON) */
+ struct {
+ /* Maximum PDU size */
+ uint32_t maximum_pdu_size;
+
+ /* Flash protection status */
+ uint32_t flash_protection;
+
+ /* Offset of the other region */
+ uint32_t offset;
+
+ /* Version string of the other region */
+ char version[32];
+
+ /* Minimum rollback version that RO will accept */
+ int32_t min_rollback;
+
+ /* RO public key version */
+ uint32_t key_version;
+ } common;
+ };
+};
- /* The below fields are present in versions 5 and up */
- /* keyids of the currently active RO and RW sections. */
- uint32_t keyid[2];
+enum first_response_pdu_header_type {
+ UPDATE_HEADER_TYPE_CR50 = 0, /* Must be 0 for backwards compatibility */
+ UPDATE_HEADER_TYPE_COMMON = 1,
};
/* TODO: Handle this in update_fw.c, not usb_update.c */