summaryrefslogtreecommitdiff
path: root/chip
diff options
context:
space:
mode:
authorNick Sanders <nsanders@chromium.org>2017-06-15 19:39:29 -0700
committerchrome-bot <chrome-bot@chromium.org>2017-06-16 17:24:28 -0700
commitfd528684dd5fae6fcad45678a9cd64a1cf6febac (patch)
tree0399fd086b257e9c43a22798020291cfda959cb6 /chip
parent28167cbc26015571eea3b9ed0344f03851acb4e4 (diff)
downloadchrome-ec-fd528684dd5fae6fcad45678a9cd64a1cf6febac.tar.gz
mn50: fix usb_update
Add support for update related vendor commands in mn50 by relocating relevant code from board/cr50 to chip/g. BUG=b:36910757 BRANCH=None TEST=./extra/usb_updater/usb_updater -d 18d1:502a build/mn50/ec.bin Change-Id: Iec0fe5585b5b6eb099f9254dfb0e5b02d5106abc Reviewed-on: https://chromium-review.googlesource.com/537999 Commit-Ready: Nick Sanders <nsanders@chromium.org> Tested-by: Nick Sanders <nsanders@chromium.org> Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
Diffstat (limited to 'chip')
-rw-r--r--chip/g/build.mk2
-rw-r--r--chip/g/post_reset.c39
-rw-r--r--chip/g/upgrade.c150
3 files changed, 190 insertions, 1 deletions
diff --git a/chip/g/build.mk b/chip/g/build.mk
index e8eec5f06e..692d4ec320 100644
--- a/chip/g/build.mk
+++ b/chip/g/build.mk
@@ -66,7 +66,7 @@ chip-y+= pmu.o
chip-y+= trng.o
chip-y+= runlevel.o
chip-$(CONFIG_USB_FW_UPDATE)+= usb_upgrade.o
-chip-$(CONFIG_NON_HC_FW_UPDATE)+= upgrade_fw.o
+chip-$(CONFIG_NON_HC_FW_UPDATE)+= upgrade_fw.o post_reset.o upgrade.o
chip-$(CONFIG_SPS)+= sps.o
chip-$(CONFIG_TPM_SPS)+=sps_tpm.o
chip-$(CONFIG_WATCHDOG)+=watchdog.o
diff --git a/chip/g/post_reset.c b/chip/g/post_reset.c
new file mode 100644
index 0000000000..24a98a9470
--- /dev/null
+++ b/chip/g/post_reset.c
@@ -0,0 +1,39 @@
+/* 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 "config.h"
+#include "board.h"
+#include "console.h"
+#include "extension.h"
+#include "system.h"
+
+#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args)
+
+void post_reset_command_handler(void *body,
+ size_t cmd_size,
+ size_t *response_size)
+{
+ *response_size = 1;
+ ((uint8_t *)body)[0] = 0;
+ post_reboot_request();
+}
+
+DECLARE_EXTENSION_COMMAND(EXTENSION_POST_RESET, post_reset_command_handler);
+
+static enum vendor_cmd_rc immediate_reset(enum vendor_cmd_cc code,
+ void *buf,
+ size_t input_size,
+ size_t *response_size)
+{
+ CPRINTS("%s: rebooting on host's request", __func__);
+ cflush(); /* Let the console drain. */
+ /* This will never return. */
+ system_reset(SYSTEM_RESET_MANUALLY_TRIGGERED | SYSTEM_RESET_HARD);
+
+ /* Never reached. */
+ return VENDOR_RC_SUCCESS;
+}
+DECLARE_VENDOR_COMMAND(VENDOR_CC_IMMEDIATE_RESET, immediate_reset);
diff --git a/chip/g/upgrade.c b/chip/g/upgrade.c
new file mode 100644
index 0000000000..c51faf401e
--- /dev/null
+++ b/chip/g/upgrade.c
@@ -0,0 +1,150 @@
+/* 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 "config.h"
+#include "console.h"
+#include "endian.h"
+#include "extension.h"
+#include "flash.h"
+#include "flash_info.h"
+#include "hooks.h"
+#include "signed_header.h"
+#include "system.h"
+#include "upgrade_fw.h"
+#include "util.h"
+
+#define CPRINTF(format, args...) cprintf(CC_EXTENSION, format, ## args)
+
+static void deferred_reboot(void)
+{
+ system_reset(SYSTEM_RESET_MANUALLY_TRIGGERED | SYSTEM_RESET_HARD);
+}
+DECLARE_DEFERRED(deferred_reboot);
+
+#define MAX_REBOOT_TIMEOUT_MS 1000
+
+/*
+ * Verify if the header at the passed in flash offset needs to be restored,
+ * and restore it if so. If this is an RO header - enable writing into that RO
+ * section (the currently active RO writes can not be enabled).
+ *
+ * Return true if a corruption was detected and restored.
+ */
+static int header_restored(uint32_t offset)
+{
+ struct SignedHeader *header;
+ uint32_t new_size;
+
+ header = (struct SignedHeader *)(CONFIG_PROGRAM_MEMORY_BASE + offset);
+
+ new_size = header->image_size;
+ if (!(new_size & TOP_IMAGE_SIZE_BIT))
+ return 0;
+
+ new_size &= ~TOP_IMAGE_SIZE_BIT;
+ /*
+ * Clear only in case the size is sensible (i.e. not set to all
+ * ones).
+ */
+ if (new_size > CONFIG_RW_SIZE)
+ return 0;
+
+ if ((offset == CONFIG_RO_MEM_OFF) || (offset == CHIP_RO_B_MEM_OFF))
+ flash_open_ro_window(offset, sizeof(struct SignedHeader));
+
+ return flash_physical_write(offset + offsetof(struct SignedHeader,
+ image_size),
+ sizeof(header->image_size),
+ (char *)&new_size) == EC_SUCCESS;
+}
+
+/*
+ * Try restoring inactive RO and RW headers, Return the number of restored
+ * headers.
+ */
+static uint8_t headers_restored(void)
+{
+ uint8_t total_restored;
+
+ /* Examine the RO first. */
+ if (system_get_ro_image_copy() == SYSTEM_IMAGE_RO)
+ total_restored = header_restored(CHIP_RO_B_MEM_OFF);
+ else
+ total_restored = header_restored(CONFIG_RO_MEM_OFF);
+
+ /* Now the RW */
+ if (system_get_image_copy() == SYSTEM_IMAGE_RW)
+ total_restored += header_restored(CONFIG_RW_B_MEM_OFF);
+ else
+ total_restored += header_restored(CONFIG_RW_MEM_OFF);
+
+ return total_restored;
+}
+
+/*
+ * The TURN_UPDATE_ON command comes with a single parameter, which is a 16 bit
+ * integer value of the number of milliseconds to wait before reboot in case
+ * there has been an update waiting.
+ *
+ * Maximum wait time is 1000 ms.
+ *
+ * If the requested timeout exceeds the allowed maximum, or the command is
+ * malformed, a protocol error is returned.
+ *
+ * If there was no errors, the number of restored headers is returned to the
+ * host in a single byte.
+ *
+ * If at least one header was restored AND the host supplied a nonzero timeout
+ * value, the H1 will be reset after this many milliseconds.
+ *
+ * Sending this command with the zero timeout value results in reporting to
+ * the host how many headers were restored, the reset is not triggered.
+ */
+static enum vendor_cmd_rc turn_update_on(enum vendor_cmd_cc code,
+ void *buf,
+ size_t input_size,
+ size_t *response_size)
+{
+ uint16_t timeout;
+ uint8_t *response;
+
+ /* Just in case. */
+ *response_size = 0;
+
+ if (input_size < sizeof(uint16_t)) {
+ CPRINTF("%s: incorrect request size %d\n",
+ __func__, input_size);
+ return VENDOR_RC_BOGUS_ARGS;
+ }
+
+ /* Retrieve the requested timeout. */
+ memcpy(&timeout, buf, sizeof(timeout));
+ timeout = be16toh(timeout);
+
+ if (timeout > MAX_REBOOT_TIMEOUT_MS) {
+ CPRINTF("%s: incorrect timeout value %d\n",
+ __func__, timeout);
+ return VENDOR_RC_BOGUS_ARGS;
+ }
+
+ *response_size = 1;
+ response = buf;
+
+ *response = headers_restored();
+ if (*response && timeout) {
+ /*
+ * At least one header was restored, and timeout is not zero,
+ * set up the reboot.
+ */
+ CPRINTF("%s: rebooting in %d ms\n", __func__, timeout);
+ hook_call_deferred(&deferred_reboot_data, timeout * MSEC);
+ }
+
+ return VENDOR_RC_SUCCESS;
+}
+DECLARE_VENDOR_COMMAND(VENDOR_CC_TURN_UPDATE_ON, turn_update_on);
+
+/* This command's implementation is shared with USB updater. */
+DECLARE_EXTENSION_COMMAND(EXTENSION_FW_UPGRADE, fw_upgrade_command_handler);