diff options
author | Namyoon Woo <namyoon@chromium.org> | 2020-02-13 10:59:06 -0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-02-20 02:08:12 +0000 |
commit | 78138c43f210c6ea59b249863d4e754a2803fd5d (patch) | |
tree | 6120fcd01f109bd5038f66e8c1222cf32e152c46 | |
parent | 38f6e45971620382dd03d48a22120cef71db0179 (diff) | |
download | chrome-ec-78138c43f210c6ea59b249863d4e754a2803fd5d.tar.gz |
restructure EC-EFS module
- add ec_efs, which tracks the system boot mode.
- add ec_comm.h header file for EC-EFS related functions.
- revised vboot.h header file.
BUG=b:141143112
BRANCH=cr50
TEST=none
Change-Id: Iec1bf466b832bac5ad6be8a52304c1d699a38fb2
Signed-off-by: Namyoon Woo <namyoon@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2055363
Reviewed-by: Mary Ruthven <mruthven@chromium.org>
-rw-r--r-- | board/cr50/board.c | 9 | ||||
-rw-r--r-- | board/cr50/board.h | 18 | ||||
-rw-r--r-- | board/cr50/build.mk | 1 | ||||
-rw-r--r-- | board/cr50/ec_comm.c | 7 | ||||
-rw-r--r-- | board/cr50/ec_comm.h | 33 | ||||
-rw-r--r-- | board/cr50/ec_efs.c | 76 | ||||
-rw-r--r-- | board/cr50/rdd.c | 1 | ||||
-rw-r--r-- | board/cr50/servo_state.c | 1 | ||||
-rw-r--r-- | chip/g/usart.c | 3 | ||||
-rw-r--r-- | include/vboot.h | 20 |
10 files changed, 148 insertions, 21 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c index 2edf27a511..f1d4d2a743 100644 --- a/board/cr50/board.c +++ b/board/cr50/board.c @@ -9,6 +9,7 @@ #include "common.h" #include "console.h" #include "dcrypto/dcrypto.h" +#include "ec_comm.h" #include "ec_version.h" #include "endian.h" #include "extension.h" @@ -1045,6 +1046,12 @@ void board_reboot_ec(void) } DECLARE_DEFERRED(board_reboot_ec); +void board_reboot_ec_deferred(int32_t usec_delay) +{ + if (usec_delay >= 0) + hook_call_deferred(&board_reboot_ec_data, usec_delay); +} + /* * This interrupt handler will be called if the RBOX key combo is detected. */ @@ -1141,6 +1148,8 @@ void assert_ec_rst(void) /* Prevent bit bang interrupt storm. */ if (uart_bitbang_is_enabled()) task_disable_irq(bitbang_config.rx_irq); + else if (board_has_ec_cr50_comm_support()) + ec_efs_reset(); wait_ec_rst(1); diff --git a/board/cr50/board.h b/board/cr50/board.h index 4c35fb9e07..25f8452503 100644 --- a/board/cr50/board.h +++ b/board/cr50/board.h @@ -341,6 +341,12 @@ int board_fwmp_allows_unlock(void); int board_vboot_dev_mode_enabled(void); void board_reboot_ap(void); void board_reboot_ec(void); +/** + * Reboot the EC + * @param usec_delay microseconds to delay in rebooting EC. + * negative input shall be disregarded. + */ +void board_reboot_ec_deferred(int usec_delay); void board_closed_loop_reset(void); int board_wipe_tpm(int reset_required); int board_is_first_factory_boot(void); @@ -380,18 +386,6 @@ void board_unwedge_i2cs(void); int board_in_prod_mode(void); -/* GPIO Interrupt handler for GPIO_EC_PACKET_MODE_EN rising edge */ -void ec_comm_packet_mode_en(enum gpio_signal unsed); - -/* GPIO Interrupt handler for GPIO_EC_PACKET_MODE_DIS falling edge */ -void ec_comm_packet_mode_dis(enum gpio_signal unsed); - -/* - * Return True if the given UART is in packet mode, in which EC-CR50 - * communication is on-going. - */ -int ec_comm_is_uart_in_packet_mode(int uart); - #endif /* !__ASSEMBLER__ */ /* USB interface indexes (use define rather than enum to expand them) */ diff --git a/board/cr50/build.mk b/board/cr50/build.mk index dfef2b1847..4b28c91641 100644 --- a/board/cr50/build.mk +++ b/board/cr50/build.mk @@ -43,6 +43,7 @@ board-y = board.o board-y += ap_state.o board-y += closed_source_set1.o board-y += ec_comm.o +board-y += ec_efs.o board-y += ec_state.o board-y += power_button.o board-y += servo_state.o diff --git a/board/cr50/ec_comm.c b/board/cr50/ec_comm.c index 3e9a343f2c..d9b01c92e2 100644 --- a/board/cr50/ec_comm.c +++ b/board/cr50/ec_comm.c @@ -6,6 +6,7 @@ */ #include "common.h" #include "console.h" +#include "ec_comm.h" #include "gpio.h" #include "hooks.h" #include "system.h" @@ -44,6 +45,12 @@ static void ec_comm_init_(void) } DECLARE_HOOK(HOOK_INIT, ec_comm_init_, HOOK_PRIO_DEFAULT + 1); +int ec_comm_process_packet(uint8_t ch) +{ + /* TODO(b:141143112): Implement this */ + return 0; +} + void ec_comm_packet_mode_en(enum gpio_signal unsed) { disable_sleep(SLEEP_MASK_EC_CR50_COMM); diff --git a/board/cr50/ec_comm.h b/board/cr50/ec_comm.h new file mode 100644 index 0000000000..37732e69c2 --- /dev/null +++ b/board/cr50/ec_comm.h @@ -0,0 +1,33 @@ +/* Copyright 2020 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. + */ +#ifndef __CROS_EC_COMM_H +#define __CROS_EC_COMM_H +#include <stdint.h> +#include "common.h" +/* GPIO Interrupt handler for GPIO_EC_PACKET_MODE_EN rising edge */ +void ec_comm_packet_mode_en(enum gpio_signal unsed); +/* GPIO Interrupt handler for GPIO_EC_PACKET_MODE_DIS falling edge */ +void ec_comm_packet_mode_dis(enum gpio_signal unsed); +/* + * Return True if the given UART is in packet mode, in which EC-CR50 + * communication is on-going. + */ +int ec_comm_is_uart_in_packet_mode(int uart); +/* + * Try to process the given char as a EC-CR50 communication packet. + * If EC-CR50 communication is broken or uninitiated yet, then + * it does not process it. + * + * @return 1 if the given char was detected and processed as a part of packet. + * 0 otherwise. + */ +int ec_comm_process_packet(uint8_t ch); +/* Reset EC EFS context */ +void ec_efs_reset(void); +/* Set EC-EFS boot_mode */ +uint16_t ec_efs_set_boot_mode(const char *data, const uint8_t size); +/* Verify the given hash data against the EC-FW hash from kernel secdata */ +uint16_t ec_efs_verify_hash(const char *hash_data, const uint8_t size); +#endif /* __CROS_EC_COMM_H */ diff --git a/board/cr50/ec_efs.c b/board/cr50/ec_efs.c new file mode 100644 index 0000000000..da5a31f019 --- /dev/null +++ b/board/cr50/ec_efs.c @@ -0,0 +1,76 @@ +/* Copyright 2020 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. + * + * EC-EFS (Early Firmware Selection) + */ +#include "common.h" +#include "console.h" +#include "ec_comm.h" +#include "ec_commands.h" +#include "hooks.h" +#include "registers.h" +#include "system.h" +#include "vboot.h" + +#ifdef CR50_DEV +#define CPRINTS(format, args...) cprints(CC_TASK, "EC-EFS: " format, ## args) +#else +#define CPRINTS(format, args...) do { } while (0) +#endif + +/* + * Context of EC-EFS + */ +static struct ec_efs_context_ { + uint32_t boot_mode:8; /* enum ec_efs_boot_mode */ + uint32_t hash_is_loaded:1; /* Is EC hash loaded from nvmem */ + uint32_t reserved:23; + + uint32_t secdata_error_code; + + uint8_t hash[SHA256_DIGEST_SIZE]; /* EC-RW digest */ +} ec_efs_ctx; + +/* + * Change the boot mode + * + * @param mode_val New boot mode value to change + */ +static void set_boot_mode_(uint8_t mode_val) +{ + CPRINTS("boot_mode: 0x%02x -> 0x%02x", ec_efs_ctx.boot_mode, mode_val); + + ec_efs_ctx.boot_mode = mode_val; + + /* Backup some ec_efs context to scratch register */ + GREG32(PMU, PWRDN_SCRATCH20) &= ~0xff; + GREG32(PMU, PWRDN_SCRATCH20) |= mode_val; +} + +/* + * Initialize EC-EFS context. + */ +static void ec_efs_init_(void) +{ + if (!board_has_ec_cr50_comm_support()) + return; + + /* + * If it is a wakeup from deep sleep, then recover some core EC-EFS + * context values, including the boot_mode value, from a PWRD_SCRATCH + * register. Otherwise, reset boot_mode. + */ + if (system_get_reset_flags() & EC_RESET_FLAG_HIBERNATE) + set_boot_mode_(GREG32(PMU, PWRDN_SCRATCH20) & 0xff); + else + ec_efs_reset(); + + /* TODO(crbug/1020578): Read Hash from Kernel NV Index */ +} +DECLARE_HOOK(HOOK_INIT, ec_efs_init_, HOOK_PRIO_DEFAULT); + +void ec_efs_reset(void) +{ + set_boot_mode_(EC_EFS_BOOT_MODE_NORMAL); +} diff --git a/board/cr50/rdd.c b/board/cr50/rdd.c index 7a4b2de8d3..2e5ccc7e81 100644 --- a/board/cr50/rdd.c +++ b/board/cr50/rdd.c @@ -6,6 +6,7 @@ #include "case_closed_debug.h" /* For ccd_ext_is_enabled() */ #include "ccd_config.h" #include "console.h" +#include "ec_comm.h" #include "gpio.h" #include "hooks.h" #include "i2c.h" diff --git a/board/cr50/servo_state.c b/board/cr50/servo_state.c index 5c05d2bb77..4e3cdff27c 100644 --- a/board/cr50/servo_state.c +++ b/board/cr50/servo_state.c @@ -6,6 +6,7 @@ */ #include "common.h" #include "console.h" +#include "ec_comm.h" #include "gpio.h" #include "hooks.h" #include "uart_bitbang.h" diff --git a/chip/g/usart.c b/chip/g/usart.c index 68ab726814..b597cb3f93 100644 --- a/chip/g/usart.c +++ b/chip/g/usart.c @@ -3,6 +3,9 @@ * found in the LICENSE file. */ +#ifdef BOARD_CR50 +#include "ec_comm.h" +#endif #include "queue.h" #include "queue_policies.h" #ifdef CONFIG_STREAM_SIGNATURE diff --git a/include/vboot.h b/include/vboot.h index 6c5f8a98b4..195db31a54 100644 --- a/include/vboot.h +++ b/include/vboot.h @@ -8,7 +8,9 @@ #include "common.h" #include "vb21_struct.h" #include "rsa.h" +#include "sha256.h" +#define CR50_COMM_VERSION 0x00 #define CR50_COMM_PREAMBLE 0xec #define MIN_LENGTH_PREAMBLE 4 #define CR50_COMM_MAGIC_CHAR0 'E' @@ -28,11 +30,12 @@ struct cr50_comm_packet { /* Header */ uint16_t magic; /* CR50_COMM_MAGIC_WORD */ + uint8_t version;/* Struct version. 4MSB=Major. 4LSB=Minor. */ uint8_t crc; /* checksum computed from all bytes after crc */ - uint16_t cmd; /* CR50_COMM_CMD_* if it is sent by EC. */ - /* CR50_COMM_RESPONSE(X) if it is sent by CR50. */ - uint8_t size; /* size of 'data[]' member. */ - uint8_t data[]; /* payload */ + uint16_t cmd; /* CR50_COMM_CMD_* if EC sends */ + /* CR50_COMM_RESPONSE(X) if CR50 sends. */ + uint8_t size; /* Size of 'data[]' member. */ + uint8_t data[]; /* Payload */ } __packed; #define CR50_COMM_MAX_DATA_SIZE 32 @@ -52,8 +55,10 @@ struct cr50_comm_packet { #define CR50_COMM_ERROR_CRC CR50_COMM_RESPONSE(0x03) #define CR50_COMM_ERROR_SIZE CR50_COMM_RESPONSE(0x04) #define CR50_COMM_ERROR_TIMEOUT CR50_COMM_RESPONSE(0x05) -#define CR50_COMM_ERROR_HASH_MISMATCH CR50_COMM_RESPONSE(0x06) -#define CR50_COMM_ERROR_UNDEFINED_CMD CR50_COMM_RESPONSE(0x07) +#define CR50_COMM_ERROR_UNDEFINED_CMD CR50_COMM_RESPONSE(0x06) +#define CR50_COMM_ERROR_BAD_PAYLOAD CR50_COMM_RESPONSE(0x07) +#define CR50_COMM_ERROR_STRUCT_VERSION CR50_COMM_RESPONSE(0x08) +#define CR50_COMM_ERROR_NVMEM CR50_COMM_RESPONSE(0x09) /* * BIT(0) : NO_BOOT flag @@ -62,9 +67,6 @@ struct cr50_comm_packet { enum ec_efs_boot_mode { EC_EFS_BOOT_MODE_NORMAL = 0x00, EC_EFS_BOOT_MODE_NO_BOOT = 0x01, - EC_EFS_BOOT_MODE_RECOVERY = 0x02, - EC_EFS_BOOT_MODE_NO_BOOT_RECOVERY = 0x03, - EC_EFS_BOOT_MODE_RESET = 0xff, /* boot_mode is uint8_t */ EC_EFS_BOOT_MODE_LIMIT = 255, |