From a89c0928fd0339d12645d6c15f2b3010b1429977 Mon Sep 17 00:00:00 2001 From: Namyoon Woo Date: Fri, 13 Mar 2020 10:58:16 -0700 Subject: remove CONFIG_USB_HID_KEYBOARD and CONFIG_USB_UPDATE This path removes CONFIG_USB_HID_KEYBOARD support and CONFIG_USB_UPDATE support because they are not used in any cr5X board configuration. Ths patch also removes some subsidiary configs as upload hook script guides. > CONFIG_USB_PAIRING > CONFIG_TOUCHPAD_VIRTUAL_OFF > CONFIG_USB_CONSOLE_READ BUG=none BRANCH=cr50 TEST=make buildall Signed-off-by: Namyoon Woo Change-Id: Iafa553fdf58772744b1d9a5c7f5460f42264f468 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2103045 Tested-by: Namyoon Woo Reviewed-by: Mary Ruthven Commit-Queue: Namyoon Woo --- common/build.mk | 4 - common/update_fw.c | 334 ----------------------------- common/usb_update.c | 594 ---------------------------------------------------- 3 files changed, 932 deletions(-) delete mode 100644 common/update_fw.c delete mode 100644 common/usb_update.c (limited to 'common') diff --git a/common/build.mk b/common/build.mk index 5e803b970b..0032ea069c 100644 --- a/common/build.mk +++ b/common/build.mk @@ -147,7 +147,6 @@ common-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_protocol.o usb_pd_policy.o endif common-$(CONFIG_USB_PD_LOGGING)+=event_log.o pd_log.o common-$(CONFIG_USB_PD_TCPC)+=usb_pd_tcpc.o -common-$(CONFIG_USB_UPDATE)+=usb_update.o update_fw.o common-$(CONFIG_USBC_PPC)+=usbc_ppc.o common-$(CONFIG_VBOOT_EFS)+=vboot/vboot.o common-$(CONFIG_VBOOT_HASH)+=sha256.o vboot_hash.o @@ -215,9 +214,6 @@ endif endif # CONFIG_BOOTBLOCK ifneq ($(CONFIG_TOUCHPAD_HASH_FW),) -$(out)/RO/common/update_fw.o: $(out)/touchpad_fw_hash.h -$(out)/RW/common/update_fw.o: $(out)/touchpad_fw_hash.h - $(out)/touchpad_fw_hash.h: $(out)/util/gen_touchpad_hash $(out)/.touchpad_fw $(call quiet,tp_hash,TPHASH ) diff --git a/common/update_fw.c b/common/update_fw.c deleted file mode 100644 index 2501f29934..0000000000 --- a/common/update_fw.c +++ /dev/null @@ -1,334 +0,0 @@ -/* Copyright 2016 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. - */ - -#include "byteorder.h" -#include "console.h" -#include "extension.h" -#include "flash.h" -#include "hooks.h" -#include "include/compile_time_macros.h" -#include "rollback.h" -#include "rwsig.h" -#include "sha256.h" -#include "system.h" -#include "uart.h" -#include "update_fw.h" -#include "util.h" -#include "vb21_struct.h" - -#if defined(CONFIG_TOUCHPAD_VIRTUAL_OFF) && defined(CONFIG_TOUCHPAD_HASH_FW) -#define CONFIG_TOUCHPAD_FW_CHUNKS \ - (CONFIG_TOUCHPAD_VIRTUAL_SIZE / CONFIG_UPDATE_PDU_SIZE) - -#include "touchpad_fw_hash.h" - -BUILD_ASSERT(sizeof(touchpad_fw_hashes) == - (CONFIG_TOUCHPAD_FW_CHUNKS * SHA256_DIGEST_SIZE)); -BUILD_ASSERT(sizeof(touchpad_fw_hashes[0]) == SHA256_DIGEST_SIZE); - -BUILD_ASSERT(sizeof(touchpad_fw_full_hash) == SHA256_DIGEST_SIZE); -#endif - -#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args) - -/* Section to be updated (i.e. not the current section). */ -struct { - uint32_t base_offset; - uint32_t top_offset; -} update_section; - -#ifdef CONFIG_TOUCHPAD_VIRTUAL_OFF -/* - * Check if a block is within touchpad FW virtual address region, and - * is therefore meant to be flashed to the touchpad. - */ -static int is_touchpad_block(uint32_t block_offset, size_t body_size) -{ - return (block_offset >= CONFIG_TOUCHPAD_VIRTUAL_OFF) && - (block_offset + body_size) <= - (CONFIG_TOUCHPAD_VIRTUAL_OFF + - CONFIG_TOUCHPAD_VIRTUAL_SIZE); -} -#endif - -/* - * Verify that the passed in block fits into the valid area. If it does, and - * is destined to the base address of the area - erase the area contents. - * - * Return success, or indication of an erase failure or chunk not fitting into - * valid area. - * - * TODO(b/36375666): Each board/chip should be able to re-define this. - */ -static uint8_t check_update_chunk(uint32_t block_offset, size_t body_size) -{ - uint32_t base; - uint32_t size; - - /* Is this an RW chunk? */ - if (update_section.base_offset != update_section.top_offset && - (block_offset >= update_section.base_offset) && - ((block_offset + body_size) <= update_section.top_offset)) { - - base = update_section.base_offset; - size = update_section.top_offset - - update_section.base_offset; - /* - * If this is the first chunk for this section, it needs to - * be erased. - */ - if (block_offset == base) { - if (flash_physical_erase(base, size) != EC_SUCCESS) { - CPRINTF("%s:%d erase failure of 0x%x..+0x%x\n", - __func__, __LINE__, base, size); - return UPDATE_ERASE_FAILURE; - } - } - - return UPDATE_SUCCESS; - } - -#ifdef CONFIG_TOUCHPAD_VIRTUAL_OFF - if (is_touchpad_block(block_offset, body_size)) - return UPDATE_SUCCESS; -#endif - - CPRINTF("%s:%d %x, %d section base %x top %x\n", - __func__, __LINE__, - block_offset, body_size, - update_section.base_offset, - update_section.top_offset); - - return UPDATE_BAD_ADDR; - -} - -/* TODO(b/36375666): These need to be overridden for chip/g. */ -int update_pdu_valid(struct update_command *cmd_body, size_t cmd_size) -{ - return 1; -} - -static int chunk_came_too_soon(uint32_t block_offset) -{ - return 0; -} - -static void new_chunk_written(uint32_t block_offset) -{ -} - -static int contents_allowed(uint32_t block_offset, - size_t body_size, void *update_data) -{ -#if defined(CONFIG_TOUCHPAD_VIRTUAL_OFF) && defined(CONFIG_TOUCHPAD_HASH_FW) - if (is_touchpad_block(block_offset, body_size)) { - struct sha256_ctx ctx; - uint8_t *tmp; - uint32_t fw_offset = block_offset - CONFIG_TOUCHPAD_VIRTUAL_OFF; - unsigned int chunk = fw_offset / CONFIG_UPDATE_PDU_SIZE; - int good = 0; - - if (chunk >= CONFIG_TOUCHPAD_FW_CHUNKS || - (fw_offset % CONFIG_UPDATE_PDU_SIZE) != 0) { - CPRINTF("%s: TP invalid offset %08x\n", - __func__, fw_offset); - return 0; - } - - SHA256_init(&ctx); - SHA256_update(&ctx, update_data, body_size); - tmp = SHA256_final(&ctx); - - good = !memcmp(tmp, touchpad_fw_hashes[chunk], - SHA256_DIGEST_SIZE); - - CPRINTF("%s: TP %08x %02x..%02x (%s)\n", __func__, - fw_offset, tmp[0], tmp[31], good ? "GOOD" : "BAD"); - - return good; - } -#endif - return 1; -} - -/* - * Setup internal state (e.g. valid sections, and fill first response). - * - * Assumes rpdu is already prefilled with 0, and that version has already - * been set. May set a return_value != 0 on error. - */ -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__); - rpdu->return_value = htobe32(UPDATE_GEN_ERROR); - return; - } - - 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 - -#ifdef HAS_TASK_RWSIG - /* Do not allow the update to start if RWSIG is still running. */ - if (rwsig_get_status() == RWSIG_IN_PROGRESS) { - CPRINTF("RWSIG in progress\n"); - rpdu->return_value = htobe32(UPDATE_RWSIG_BUSY); - } -#endif -} - -void fw_update_command_handler(void *body, - size_t cmd_size, - size_t *response_size) -{ - struct update_command *cmd_body = body; - void *update_data; - uint8_t *error_code = body; /* Cache the address for code clarity. */ - size_t body_size; - uint32_t block_offset; - - *response_size = 1; /* One byte response unless this is a start PDU. */ - - if (cmd_size < sizeof(struct update_command)) { - CPRINTF("%s:%d\n", __func__, __LINE__); - *error_code = UPDATE_GEN_ERROR; - return; - } - body_size = cmd_size - sizeof(struct update_command); - - if (!cmd_body->block_base && !body_size) { - struct first_response_pdu *rpdu = body; - - /* - * This is the connection establishment request, the response - * allows the server to decide what sections of the image to - * send to program into the flash. - */ - - /* 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 = htobe16(UPDATE_PROTOCOL_VERSION); - - /* Setup internal state (e.g. valid sections, and fill rpdu) */ - fw_update_start(rpdu); - return; - } - - block_offset = be32toh(cmd_body->block_base); - - if (!update_pdu_valid(cmd_body, cmd_size)) { - *error_code = UPDATE_DATA_ERROR; - return; - } - - update_data = cmd_body + 1; - if (!contents_allowed(block_offset, body_size, update_data)) { - *error_code = UPDATE_ROLLBACK_ERROR; - return; - } - - /* Check if the block will fit into the valid area. */ - *error_code = check_update_chunk(block_offset, body_size); - if (*error_code) - return; - - if (chunk_came_too_soon(block_offset)) { - *error_code = UPDATE_RATE_LIMIT_ERROR; - return; - } - - /* - * TODO(b/36375666): chip/g code has some cr50-specific stuff right - * here, which should probably be merged into contents_allowed... - */ - -#ifdef CONFIG_TOUCHPAD_VIRTUAL_OFF - if (is_touchpad_block(block_offset, body_size)) { - if (touchpad_update_write( - block_offset - CONFIG_TOUCHPAD_VIRTUAL_OFF, - body_size, update_data) != EC_SUCCESS) { - *error_code = UPDATE_WRITE_FAILURE; - CPRINTF("%s:%d update write error\n", - __func__, __LINE__); - return; - } - - new_chunk_written(block_offset); - - *error_code = UPDATE_SUCCESS; - return; - } -#endif - - CPRINTF("update: 0x%x\n", block_offset + CONFIG_PROGRAM_MEMORY_BASE); - if (flash_physical_write(block_offset, body_size, update_data) - != EC_SUCCESS) { - *error_code = UPDATE_WRITE_FAILURE; - CPRINTF("%s:%d update write error\n", __func__, __LINE__); - return; - } - - new_chunk_written(block_offset); - - /* Verify that data was written properly. */ - if (memcmp(update_data, (void *) - (block_offset + CONFIG_PROGRAM_MEMORY_BASE), - body_size)) { - *error_code = UPDATE_VERIFY_ERROR; - CPRINTF("%s:%d update verification error\n", - __func__, __LINE__); - return; - } - - *error_code = UPDATE_SUCCESS; -} - -/* TODO(b/36375666): This need to be overridden for chip/g. */ -void fw_update_complete(void) -{ -} diff --git a/common/usb_update.c b/common/usb_update.c deleted file mode 100644 index 64875fd798..0000000000 --- a/common/usb_update.c +++ /dev/null @@ -1,594 +0,0 @@ -/* Copyright 2016 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. - */ - -#include "byteorder.h" -#include "common.h" -#include "console.h" -#include "consumer.h" -#include "curve25519.h" -#include "extension.h" -#include "flash.h" -#include "queue_policies.h" -#include "host_command.h" -#include "rollback.h" -#include "rwsig.h" -#include "sha256.h" -#include "system.h" -#include "uart.h" -#include "update_fw.h" -#include "usb-stream.h" -#include "util.h" - -#define CPRINTS(format, args...) cprints(CC_USB, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_USB, format, ## args) - -/* - * This file is an adaptation layer between the USB interface and the firmware - * update engine. The engine expects to receive long blocks of data, 1K or so - * in size, prepended by the offset where the data needs to be programmed into - * the flash and a 4 byte integrity check value. - * - * The USB transfer, on the other hand, operates on much shorter chunks of - * data, typically 64 bytes in this case. This module reassembles firmware - * programming blocks from the USB chunks, and invokes the programmer passing - * it the full block. - * - * The programmer reports results by putting the return value into the same - * buffer where the block was passed in. This wrapper retrieves the - * programmer's return value, and sends it back to the host. The return value - * is usually one byte in size, the only exception is the connection - * establishment phase where the return value is 16 bytes in size. - * - * In the end of the successful image transfer and programming, the host sends - * the reset command, and the device reboots itself. - */ - -struct consumer const update_consumer; -struct usb_stream_config const usb_update; - -static struct queue const update_to_usb = QUEUE_DIRECT(64, uint8_t, - null_producer, - usb_update.consumer); -static struct queue const usb_to_update = QUEUE_DIRECT(64, uint8_t, - usb_update.producer, - update_consumer); - -USB_STREAM_CONFIG_FULL(usb_update, - USB_IFACE_UPDATE, - USB_CLASS_VENDOR_SPEC, - USB_SUBCLASS_GOOGLE_UPDATE, - USB_PROTOCOL_GOOGLE_UPDATE, - USB_STR_UPDATE_NAME, - USB_EP_UPDATE, - USB_MAX_PACKET_SIZE, - USB_MAX_PACKET_SIZE, - usb_to_update, - update_to_usb) - - -/* The receiver can be in one of the states below. */ -enum rx_state { - rx_idle, /* Nothing happened yet. */ - rx_inside_block, /* Assembling a block to pass to the programmer. */ - rx_outside_block, /* Waiting for the next block to start or for the - reset command. */ -}; - -enum rx_state rx_state_ = rx_idle; -static uint8_t block_buffer[sizeof(struct update_command) + - CONFIG_UPDATE_PDU_SIZE]; -static uint32_t block_size; -static uint32_t block_index; - -#ifdef CONFIG_USB_PAIRING -#define KEY_CONTEXT "device-identity" - -static int pair_challenge(struct pair_challenge *challenge) -{ - uint8_t response; - - /* Scratchpad for device secret and x25519 public/shared key. */ - uint8_t tmp[32]; - BUILD_ASSERT(sizeof(tmp) >= X25519_PUBLIC_VALUE_LEN); - BUILD_ASSERT(sizeof(tmp) >= X25519_PRIVATE_KEY_LEN); - BUILD_ASSERT(sizeof(tmp) >= CONFIG_ROLLBACK_SECRET_SIZE); - - /* Scratchpad for device_private and authenticator. */ - uint8_t tmp2[32]; - BUILD_ASSERT(sizeof(tmp2) >= X25519_PRIVATE_KEY_LEN); - BUILD_ASSERT(sizeof(tmp2) >= SHA256_DIGEST_SIZE); - - /* tmp = device_secret */ - if (rollback_get_secret(tmp) != EC_SUCCESS) { - response = EC_RES_UNAVAILABLE; - QUEUE_ADD_UNITS(&update_to_usb, &response, sizeof(response)); - return 1; - } - - /* - * Nothing can fail from now on, let's push data to the queue as soon as - * possible to save some temporary variables. - */ - response = EC_RES_SUCCESS; - QUEUE_ADD_UNITS(&update_to_usb, &response, sizeof(response)); - - /* - * tmp2 = device_private - * = HMAC_SHA256(device_secret, "device-identity") - */ - hmac_SHA256(tmp2, tmp, CONFIG_ROLLBACK_SECRET_SIZE, - KEY_CONTEXT, sizeof(KEY_CONTEXT) - 1); - - /* tmp = device_public = x25519(device_private, x25519_base_point) */ - X25519_public_from_private(tmp, tmp2); - QUEUE_ADD_UNITS(&update_to_usb, tmp, sizeof(tmp)); - - /* tmp = shared_secret = x25519(device_private, host_public) */ - X25519(tmp, tmp2, challenge->host_public); - - /* tmp2 = authenticator = HMAC_SHA256(shared_secret, nonce) */ - hmac_SHA256(tmp2, tmp, sizeof(tmp), - challenge->nonce, sizeof(challenge->nonce)); - QUEUE_ADD_UNITS(&update_to_usb, tmp2, - member_size(struct pair_challenge_response, authenticator)); - return 1; -} -#endif - -/* - * Fetches a transfer start frame from the queue. This can be either an update - * start frame (block_size = 0, all of cmd = 0), or the beginning of a frame - * (block_size > 0, valid block_base in cmd). - */ -static int fetch_transfer_start(struct consumer const *consumer, size_t count, - struct update_frame_header *pupfr) -{ - int i; - - /* - * Let's just make sure we drain the queue no matter what the contents - * are. This way they won't be in the way during next callback, even - * if these contents are not what's expected. - * - * Note: If count > sizeof(*pupfr), pupfr will be corrupted. This is - * ok as we will immediately fail after this. - */ - i = count; - while (i > 0) { - QUEUE_REMOVE_UNITS(consumer->queue, pupfr, - MIN(i, sizeof(*pupfr))); - i -= sizeof(*pupfr); - } - - if (count != sizeof(struct update_frame_header)) { - CPRINTS("FW update: wrong first block, size %d", count); - return 0; - } - - return 1; -} - -static int try_vendor_command(struct consumer const *consumer, size_t count) -{ - char buffer[USB_MAX_PACKET_SIZE]; - struct update_frame_header *cmd_buffer = (void *)buffer; - int rv = 0; - - /* Validate count (too short, or too long). */ - if (count < sizeof(*cmd_buffer) || count > sizeof(buffer)) - return 0; - - /* - * Let's copy off the queue the update frame header, to see if this - * is a channeled vendor command. - */ - queue_peek_units(consumer->queue, cmd_buffer, 0, sizeof(*cmd_buffer)); - if (be32toh(cmd_buffer->cmd.block_base) != UPDATE_EXTRA_CMD) - return 0; - - if (be32toh(cmd_buffer->block_size) != count) { - CPRINTS("%s: problem: block size and count mismatch (%d != %d)", - __func__, be32toh(cmd_buffer->block_size), count); - return 0; - } - - /* Get the entire command, don't remove it from the queue just yet. */ - queue_peek_units(consumer->queue, cmd_buffer, 0, count); - - /* Looks like this is a vendor command, let's verify it. */ - if (update_pdu_valid(&cmd_buffer->cmd, - count - offsetof(struct update_frame_header, cmd))) { - enum update_extra_command subcommand; - uint8_t response; - size_t response_size = sizeof(response); - int __attribute__((unused)) header_size; - int __attribute__((unused)) data_count; - - /* looks good, let's process it. */ - rv = 1; - - /* Now remove it from the queue. */ - queue_advance_head(consumer->queue, count); - - subcommand = be16toh(*((uint16_t *)(cmd_buffer + 1))); - - /* - * header size: update frame header + 2 bytes for subcommand - * data_count: Some commands take in extra data as parameter - */ - header_size = sizeof(*cmd_buffer) + sizeof(uint16_t); - data_count = count - header_size; - - switch (subcommand) { - case UPDATE_EXTRA_CMD_IMMEDIATE_RESET: - CPRINTS("Rebooting!"); - CPRINTF("\n\n"); - cflush(); - system_reset(SYSTEM_RESET_MANUALLY_TRIGGERED); - /* Unreachable, unless something bad happens. */ - response = EC_RES_ERROR; - break; - case UPDATE_EXTRA_CMD_JUMP_TO_RW: -#ifdef CONFIG_RWSIG - /* - * Tell rwsig task to jump to RW. This does nothing if - * verification failed, and will only jump later on if - * verification is still in progress. - */ - rwsig_continue(); - - switch (rwsig_get_status()) { - case RWSIG_VALID: - response = EC_RES_SUCCESS; - break; - case RWSIG_INVALID: - response = EC_RES_INVALID_CHECKSUM; - break; - case RWSIG_IN_PROGRESS: - response = EC_RES_IN_PROGRESS; - break; - default: - response = EC_RES_ERROR; - } -#else - system_run_image_copy(SYSTEM_IMAGE_RW); -#endif - break; -#ifdef CONFIG_RWSIG - case UPDATE_EXTRA_CMD_STAY_IN_RO: - rwsig_abort(); - response = EC_RES_SUCCESS; - break; -#endif - case UPDATE_EXTRA_CMD_UNLOCK_RW: - flash_set_protect(EC_FLASH_PROTECT_RW_AT_BOOT, 0); - response = EC_RES_SUCCESS; - break; -#ifdef CONFIG_ROLLBACK - case UPDATE_EXTRA_CMD_UNLOCK_ROLLBACK: - flash_set_protect(EC_FLASH_PROTECT_ROLLBACK_AT_BOOT, 0); - response = EC_RES_SUCCESS; - break; -#ifdef CONFIG_ROLLBACK_SECRET_SIZE -#ifdef CONFIG_ROLLBACK_UPDATE - case UPDATE_EXTRA_CMD_INJECT_ENTROPY: { - if (data_count < CONFIG_ROLLBACK_SECRET_SIZE) { - CPRINTS("Entropy too short"); - response = EC_RES_INVALID_PARAM; - break; - } - - CPRINTS("Adding %db of entropy", data_count); - /* Add the entropy to secret. */ - rollback_add_entropy(buffer + header_size, data_count); - break; - } -#endif /* CONFIG_ROLLBACK_UPDATE */ -#ifdef CONFIG_USB_PAIRING - case UPDATE_EXTRA_CMD_PAIR_CHALLENGE: { - if (data_count < sizeof(struct pair_challenge)) { - CPRINTS("Challenge data too short"); - response = EC_RES_INVALID_PARAM; - break; - } - - /* pair_challenge takes care of answering */ - return pair_challenge((struct pair_challenge *) - (buffer + header_size)); - } -#endif -#endif /* CONFIG_ROLLBACK_SECRET_SIZE */ -#endif /* CONFIG_ROLLBACK */ -#ifdef CONFIG_TOUCHPAD - case UPDATE_EXTRA_CMD_TOUCHPAD_INFO: { - struct touchpad_info tp = { 0 }; - - if (data_count != 0) { - response = EC_RES_INVALID_PARAM; - break; - } - - response_size = touchpad_get_info(&tp); - if (response_size < 1) { - response = EC_RES_ERROR; - break; - } - -#ifdef CONFIG_TOUCHPAD_VIRTUAL_OFF - tp.fw_address = CONFIG_TOUCHPAD_VIRTUAL_OFF; - tp.fw_size = CONFIG_TOUCHPAD_VIRTUAL_SIZE; - -#ifdef CONFIG_TOUCHPAD_HASH_FW - memcpy(tp.allowed_fw_hash, touchpad_fw_full_hash, - sizeof(tp.allowed_fw_hash)); -#endif -#endif /* CONFIG_TOUCHPAD_VIRTUAL_OFF */ - QUEUE_ADD_UNITS(&update_to_usb, - &tp, response_size); - return 1; - } - case UPDATE_EXTRA_CMD_TOUCHPAD_DEBUG: { - uint8_t *data = NULL; - unsigned int write_count = 0; - - /* - * Let the touchpad driver decide what it wants to do - * with the payload data, and put the response in data. - */ - response = touchpad_debug(buffer + header_size, - data_count, &data, &write_count); - - /* - * On error, or if there is no data to write back, just - * write back response. - */ - if (response != EC_RES_SUCCESS || write_count == 0) - break; - - /* Check that we can write all the data to the queue. */ - if (write_count > queue_space(&update_to_usb)) - return EC_RES_BUSY; - - QUEUE_ADD_UNITS(&update_to_usb, data, write_count); - return 1; - } -#endif -#ifdef CONFIG_USB_CONSOLE_READ - /* - * TODO(b/112877237): move this to a new interface, so we can - * support reading log and other commands at the same time? - */ - case UPDATE_EXTRA_CMD_CONSOLE_READ_INIT: - response = uart_console_read_buffer_init(); - break; - case UPDATE_EXTRA_CMD_CONSOLE_READ_NEXT: { - uint8_t *data = buffer + header_size; - uint8_t output[64]; - uint16_t write_count = 0; - - if (data_count != 1) { - response = EC_RES_INVALID_PARAM; - break; - } - - response = uart_console_read_buffer( - data[0], - (char *)output, - MIN(sizeof(output), - queue_space(&update_to_usb)), - &write_count); - if (response != EC_RES_SUCCESS || write_count == 0) - break; - - QUEUE_ADD_UNITS(&update_to_usb, output, write_count); - return 1; - } -#endif - default: - response = EC_RES_INVALID_COMMAND; - } - - QUEUE_ADD_UNITS(&update_to_usb, &response, response_size); - } - - return rv; -} - -/* - * When was last time a USB callback was called, in microseconds, free running - * timer. - */ -static uint64_t prev_activity_timestamp; - -/* - * A flag indicating that at least one valid PDU containing flash update block - * has been received in the current transfer session. - */ -static uint8_t data_was_transferred; - -/* Reply with an error to remote side, reset state. */ -static void send_error_reset(uint8_t resp_value) -{ - QUEUE_ADD_UNITS(&update_to_usb, &resp_value, 1); - rx_state_ = rx_idle; - data_was_transferred = 0; -} - -/* Called to deal with data from the host */ -static void update_out_handler(struct consumer const *consumer, size_t count) -{ - struct update_frame_header upfr; - size_t resp_size; - uint8_t resp_value; - uint64_t delta_time; - - /* How much time since the previous USB callback? */ - delta_time = get_time().val - prev_activity_timestamp; - prev_activity_timestamp += delta_time; - - /* If timeout exceeds 5 seconds - let's start over. */ - if ((delta_time > 5000000) && (rx_state_ != rx_idle)) { - rx_state_ = rx_idle; - CPRINTS("FW update: recovering after timeout"); - } - - if (rx_state_ == rx_idle) { - /* - * The payload must be an update initiating PDU. - * - * The size of the response returned in the same buffer will - * exceed the received frame size; Let's make sure there is - * enough room for the response in the buffer. - */ - union { - struct update_frame_header upfr; - struct { - uint32_t unused; - struct first_response_pdu startup_resp; - }; - } u; - - /* Check is this is a channeled TPM extension command. */ - if (try_vendor_command(consumer, count)) - return; - - /* - * An update start PDU is a command without any payload, with - * digest = 0, and base = 0. - */ - if (!fetch_transfer_start(consumer, count, &u.upfr) || - be32toh(u.upfr.block_size) != - sizeof(struct update_frame_header) || - u.upfr.cmd.block_digest != 0 || - u.upfr.cmd.block_base != 0) { - /* - * Something is wrong, this payload is not a valid - * update start PDU. Let'w indicate this by returning - * a single byte error code. - */ - CPRINTS("FW update: invalid start."); - send_error_reset(UPDATE_GEN_ERROR); - return; - } - - CPRINTS("FW update: starting..."); - fw_update_command_handler(&u.upfr.cmd, count - - offsetof(struct update_frame_header, - cmd), - &resp_size); - - if (!u.startup_resp.return_value) { - rx_state_ = rx_outside_block; /* We're in business. */ - data_was_transferred = 0; /* No data received yet. */ - } - - /* Let the host know what updater had to say. */ - QUEUE_ADD_UNITS(&update_to_usb, &u.startup_resp, resp_size); - return; - } - - if (rx_state_ == rx_outside_block) { - /* - * Expecting to receive the beginning of the block or the - * reset command if all data blocks have been processed. - */ - if (count == 4) { - uint32_t command; - - QUEUE_REMOVE_UNITS(consumer->queue, &command, - sizeof(command)); - command = be32toh(command); - if (command == UPDATE_DONE) { - CPRINTS("FW update: done"); - - if (data_was_transferred) { - fw_update_complete(); - data_was_transferred = 0; - } - - resp_value = 0; - QUEUE_ADD_UNITS(&update_to_usb, - &resp_value, 1); - rx_state_ = rx_idle; - return; - } - } - - /* - * At this point we expect a block start message. It is - * sizeof(upfr) bytes in size. - */ - if (!fetch_transfer_start(consumer, count, &upfr)) { - CPRINTS("Invalid block start."); - send_error_reset(UPDATE_GEN_ERROR); - return; - } - - /* Let's allocate a large enough buffer. */ - block_size = be32toh(upfr.block_size) - - offsetof(struct update_frame_header, cmd); - - /* - * Only update start PDU is allowed to have a size 0 payload. - */ - if (block_size <= sizeof(struct update_command) || - block_size > sizeof(block_buffer)) { - CPRINTS("Invalid block size (%d).", block_size); - send_error_reset(UPDATE_GEN_ERROR); - return; - } - - /* - * Copy the rest of the message into the block buffer to pass - * to the updater. - */ - block_index = sizeof(upfr) - - offsetof(struct update_frame_header, cmd); - memcpy(block_buffer, &upfr.cmd, block_index); - block_size -= block_index; - rx_state_ = rx_inside_block; - return; - } - - /* Must be inside block. */ - QUEUE_REMOVE_UNITS(consumer->queue, block_buffer + block_index, count); - block_index += count; - block_size -= count; - - if (block_size) { - if (count <= sizeof(upfr)) { - /* - * A block header size instead of chunk size message - * has been received, let's abort the transfer. - */ - CPRINTS("Unexpected header"); - send_error_reset(UPDATE_GEN_ERROR); - return; - } - return; /* More to come. */ - } - - /* - * Ok, the entire block has been received and reassembled, pass it to - * the updater for verification and programming. - */ - fw_update_command_handler(block_buffer, block_index, &resp_size); - - /* - * There was at least an attempt to program the flash, set the - * flag. - */ - data_was_transferred = 1; - resp_value = block_buffer[0]; - QUEUE_ADD_UNITS(&update_to_usb, &resp_value, sizeof(resp_value)); - rx_state_ = rx_outside_block; -} - -struct consumer const update_consumer = { - .queue = &usb_to_update, - .ops = &((struct consumer_ops const) { - .written = update_out_handler, - }), -}; -- cgit v1.2.1