summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2016-08-14 12:58:59 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-08-16 00:58:05 -0700
commit2813413f3546462d7313be4e7430415999785b76 (patch)
tree3a8020b6562af35f7266e1133ae3c40c4ea45d3f
parent5a013c26ca1c3635cd06d14ae8d20f36202fb68f (diff)
downloadchrome-ec-2813413f3546462d7313be4e7430415999785b76.tar.gz
usb_updater: refactor section transfer into a function
In preparation to RW and RO cr50 updates, separate the code transferring an image section (an RW section currently) into a function. This will allow to add RO transfer by invoking the same function with different address and size parameters. BRANCH=none BUG=chrome-os-partner:55789 TEST=verified that it is still possible to update to RW_A and RW_B both over USB and SPI. Change-Id: Ia41317e0eefe114bac41e73c7e715b1a5cb6549c Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/368988 Reviewed-by: Aseda Aboagye <aaboagye@chromium.org>
-rw-r--r--extra/usb_updater/usb_updater.c145
1 files changed, 84 insertions, 61 deletions
diff --git a/extra/usb_updater/usb_updater.c b/extra/usb_updater/usb_updater.c
index 364e8039a3..bbb276652e 100644
--- a/extra/usb_updater/usb_updater.c
+++ b/extra/usb_updater/usb_updater.c
@@ -477,72 +477,40 @@ static int transfer_block(struct usb_endpoint *uep, struct update_pdu *updu,
return 0;
}
-static void transfer_and_reboot(struct transfer_endpoint *tep,
- uint8_t *data, uint32_t data_len)
+/**
+ * Transfer an image section (typically RW or RO).
+ *
+ * tep - transfer endpoint to use to communicate with the target
+ * data_ptr - pointer at the section base in the image
+ * section_addr - address of the section in the target memory space
+ * data_len - section size
+ */
+static void transfer_section(struct transfer_endpoint *tep,
+ uint8_t *data_ptr,
+ uint32_t section_addr,
+ size_t data_len)
{
- uint32_t out;
- uint32_t reply;
- uint8_t *data_ptr;
- uint32_t next_offset;
- struct update_pdu updu;
- struct startup_resp first_resp;
- size_t rxed_size;
- struct usb_endpoint *uep = &tep->uep;
-
- /* Send start/erase request */
- printf("erase\n");
-
- memset(&updu, 0, sizeof(updu));
- updu.block_size = htobe32(sizeof(updu));
-
- if (tep->ep_type == usb_xfer) {
- do_xfer(uep, &updu, sizeof(updu), &first_resp,
- sizeof(first_resp), 1, &rxed_size);
- } else {
- rxed_size = sizeof(first_resp);
- if (tpm_send_pkt(tep->tpm_fd, 0, 0, NULL, 0,
- &first_resp, &rxed_size) < 0) {
- perror("Failed to start transfer");
- return;
- }
- }
-
- if (rxed_size == sizeof(uint32_t))
- protocol_version = 0;
- else
- protocol_version = be32toh(first_resp.version);
-
- printf("Target running protocol version %d\n", protocol_version);
-
- reply = be32toh(first_resp.value);
-
- if (reply < 256) {
- fprintf(stderr, "Target reports error %d\n", reply);
- shut_down(uep);
- }
-
- next_offset = reply - FLASH_BASE;
- data_ptr = data + next_offset;
- data_len = CONFIG_RW_SIZE;
-
- /* Actually, we can skip trailing chunks of 0xff */
+ /*
+ * Actually, we can skip trailing chunks of 0xff, as the entire
+ * section space must be erased before the update is attempted.
+ */
while (data_len && (data_ptr[data_len - 1] == 0xff))
data_len--;
- printf("sending 0x%x/0x%x bytes to %#x\n", data_len, CONFIG_RW_SIZE,
- next_offset);
+ printf("sending 0x%zx bytes to %#x\n", data_len, section_addr);
while (data_len) {
size_t payload_size;
SHA_CTX ctx;
uint8_t digest[SHA_DIGEST_LENGTH];
int max_retries;
+ struct update_pdu updu;
/* prepare the header to prepend to the block. */
payload_size = MIN(data_len, SIGNED_TRANSFER_SIZE);
updu.block_size = htobe32(payload_size +
sizeof(struct update_pdu));
- updu.cmd.block_base = htobe32(next_offset + FLASH_BASE);
+ updu.cmd.block_base = htobe32(section_addr);
/* Calculate the digest. */
SHA1_Init(&ctx);
@@ -556,42 +524,97 @@ static void transfer_and_reboot(struct transfer_endpoint *tep,
sizeof(updu.cmd.block_digest));
if (tep->ep_type == usb_xfer) {
for (max_retries = 10; max_retries; max_retries--)
- if (!transfer_block(uep, &updu,
+ if (!transfer_block(&tep->uep, &updu,
data_ptr, payload_size))
break;
if (!max_retries) {
fprintf(stderr,
- "Failed to trasfer block, %d to go\n",
+ "Failed to trasfer block, %zd to go\n",
data_len);
exit(1);
}
} else {
- rxed_size = sizeof(first_resp);
+ struct startup_resp resp;
+ size_t rxed_size;
+
+ rxed_size = sizeof(resp);
if (tpm_send_pkt(tep->tpm_fd,
updu.cmd.block_digest,
- next_offset + FLASH_BASE,
- data_ptr,
- payload_size, &first_resp,
+ section_addr,
+ data_ptr,
+ payload_size, &resp,
&rxed_size) < 0) {
fprintf(stderr,
- "Failed to trasfer block, %d to go\n",
+ "Failed to trasfer block, %zd to go\n",
data_len);
exit(1);
}
- if ((rxed_size != 1) || *((uint8_t *)&first_resp)) {
+ if ((rxed_size != 1) || *((uint8_t *)&resp)) {
fprintf(stderr,
"got response of size %zd, value %#x\n",
- rxed_size, first_resp.value);
+ rxed_size, resp.value);
exit(1);
}
}
data_len -= payload_size;
data_ptr += payload_size;
- next_offset += payload_size;
+ section_addr += payload_size;
}
+}
+
+static void transfer_and_reboot(struct transfer_endpoint *tep,
+ uint8_t *data, size_t data_len)
+{
+ uint32_t out;
+ uint32_t reply;
+ struct update_pdu updu;
+ struct startup_resp first_resp;
+ size_t rxed_size;
+ struct usb_endpoint *uep = &tep->uep;
+
+ /* Send start/erase request */
+ printf("erase\n");
+
+ memset(&updu, 0, sizeof(updu));
+ updu.block_size = htobe32(sizeof(updu));
+
+ if (tep->ep_type == usb_xfer) {
+ do_xfer(uep, &updu, sizeof(updu), &first_resp,
+ sizeof(first_resp), 1, &rxed_size);
+ } else {
+ rxed_size = sizeof(first_resp);
+ if (tpm_send_pkt(tep->tpm_fd, 0, 0, NULL, 0,
+ &first_resp, &rxed_size) < 0) {
+ perror("Failed to start transfer");
+ return;
+ }
+ }
+
+ if (rxed_size == sizeof(uint32_t))
+ protocol_version = 0;
+ else
+ protocol_version = be32toh(first_resp.version);
+
+ printf("Target running protocol version %d\n", protocol_version);
+
+ reply = be32toh(first_resp.value);
+
+ if (reply < 256) {
+ fprintf(stderr, "Target reports error %d\n", reply);
+ shut_down(uep);
+ }
+
+ if ((reply - FLASH_BASE + CONFIG_RW_SIZE) > data_len) {
+ fprintf(stderr, "Base addr of %#x too high\n", reply);
+ shut_down(uep);
+ }
+
+ transfer_section(tep, data + reply - FLASH_BASE,
+ reply, CONFIG_RW_SIZE);
+
printf("-------\nupdate complete\n");
if (tep->ep_type != usb_xfer)
return;