diff options
-rw-r--r-- | baseboard/kukui/baseboard.h | 1 | ||||
-rw-r--r-- | common/chipset.c | 27 | ||||
-rw-r--r-- | common/main.c | 16 | ||||
-rw-r--r-- | common/uart_buffering.c | 34 | ||||
-rw-r--r-- | core/cortex-m0/ec.lds.S | 28 | ||||
-rw-r--r-- | include/chipset.h | 5 | ||||
-rw-r--r-- | include/config.h | 9 | ||||
-rw-r--r-- | include/link_defs.h | 7 | ||||
-rw-r--r-- | include/uart.h | 5 | ||||
-rw-r--r-- | include/util.h | 3 |
10 files changed, 126 insertions, 9 deletions
diff --git a/baseboard/kukui/baseboard.h b/baseboard/kukui/baseboard.h index ee8428f03f..b0313bf10c 100644 --- a/baseboard/kukui/baseboard.h +++ b/baseboard/kukui/baseboard.h @@ -98,6 +98,7 @@ #define CONFIG_FORCE_CONSOLE_RESUME #define CONFIG_HOST_COMMAND_STATUS #define CONFIG_CMD_AP_RESET_LOG +#define CONFIG_PRESERVE_LOGS /* Required for FAFT */ #define CONFIG_CMD_BUTTON diff --git a/common/chipset.c b/common/chipset.c index 427ea37940..9c11abe9c0 100644 --- a/common/chipset.c +++ b/common/chipset.c @@ -10,6 +10,7 @@ #include "console.h" #include "ec_commands.h" #include "host_command.h" +#include "link_defs.h" #include "system.h" #include "task.h" #include "timer.h" @@ -60,10 +61,29 @@ DECLARE_HOST_COMMAND(EC_CMD_AP_RESET, #ifdef CONFIG_CMD_AP_RESET_LOG static struct mutex reset_log_mutex; -static int next_reset_log; +static int next_reset_log __preserved_logs(next_reset_log); static uint32_t ap_resets_since_ec_boot; /* keep reset_logs size a power of 2 */ -static struct ap_reset_log_entry reset_logs[4]; +static struct ap_reset_log_entry + reset_logs[4] __preserved_logs(reset_logs); +static int reset_log_checksum __preserved_logs(reset_log_checksum); + +/* Calculate reset log checksum */ +static int calc_reset_log_checksum(void) +{ + return next_reset_log ^ reset_logs[next_reset_log].reset_cause; +} + +/* Initialize reset logs and next reset log */ +void init_reset_log(void) +{ + if (next_reset_log < 0 || next_reset_log >= ARRAY_SIZE(reset_logs) || + reset_log_checksum != calc_reset_log_checksum()) { + reset_log_checksum = 0; + next_reset_log = 0; + memset(&reset_logs, 0, sizeof(reset_logs)); + } +} void report_ap_reset(enum chipset_shutdown_reason reason) { @@ -76,6 +96,9 @@ void report_ap_reset(enum chipset_shutdown_reason reason) next_reset_log &= ARRAY_SIZE(reset_logs) - 1; ap_resets_since_ec_boot++; mutex_unlock(&reset_log_mutex); + + /* Update checksum */ + reset_log_checksum = calc_reset_log_checksum(); } static int host_command_get_uptime_info(struct host_cmd_handler_args *args) diff --git a/common/main.c b/common/main.c index 069b20dd17..c5e63e7faa 100644 --- a/common/main.c +++ b/common/main.c @@ -39,6 +39,22 @@ test_mockable __keep int main(void) { + if (IS_ENABLED(CONFIG_PRESERVE_LOGS)) { + /* + * Initialize tx buffer head and tail. This needs to be done + * before any updates of uart tx input because we need to + * verify if the values remain the same after every EC reset. + */ + uart_init_buffer(); + + /* + * Initialize reset logs. Needs to be done before any updates of + * reset logs because we need to verify if the values remain + * the same after every EC reset. + */ + init_reset_log(); + } + /* * Pre-initialization (pre-verified boot) stage. Initialization at * this level should do as little as possible, because verified boot diff --git a/common/uart_buffering.c b/common/uart_buffering.c index 9eb6db5cdf..f1c68e7773 100644 --- a/common/uart_buffering.c +++ b/common/uart_buffering.c @@ -37,9 +37,10 @@ (CONFIG_UART_RX_DMA_RECHECKS + 1)) /* Transmit and receive buffers */ -static volatile char tx_buf[CONFIG_UART_TX_BUF_SIZE] __uncached; -static volatile int tx_buf_head; -static volatile int tx_buf_tail; +static volatile char tx_buf[CONFIG_UART_TX_BUF_SIZE] + __uncached __preserved_logs(tx_buf); +static volatile int tx_buf_head __preserved_logs(tx_buf_head); +static volatile int tx_buf_tail __preserved_logs(tx_buf_tail); static volatile char rx_buf[CONFIG_UART_RX_BUF_SIZE] __uncached; static volatile int rx_buf_head; static volatile int rx_buf_tail; @@ -47,6 +48,24 @@ static int tx_snapshot_head; static int tx_snapshot_tail; static int tx_last_snapshot_head; static int tx_next_snapshot_head; +static int tx_checksum __preserved_logs(tx_checksum); + +static int uart_buffer_calc_checksum(void) +{ + return tx_buf_head ^ tx_buf_tail; +} + + +void uart_init_buffer(void) +{ + if (tx_checksum != uart_buffer_calc_checksum() || + !IN_RANGE(tx_buf_head, 0, CONFIG_UART_TX_BUF_SIZE) || + !IN_RANGE(tx_buf_tail, 0, CONFIG_UART_TX_BUF_SIZE)) { + tx_buf_head = 0; + tx_buf_tail = 0; + tx_checksum = 0; + } +} /** * Put a single character into the transmit buffer. @@ -92,6 +111,9 @@ static int __tx_char(void *context, int c) tx_buf[tx_buf_head] = c; tx_buf_head = tx_buf_next; + + if (IS_ENABLED(CONFIG_PRESERVE_LOGS)) + tx_checksum = uart_buffer_calc_checksum(); #endif return 0; } @@ -121,6 +143,9 @@ void uart_process_output(void) tx_buf_tail = (tx_buf_tail + tx_dma_in_progress) & (CONFIG_UART_TX_BUF_SIZE - 1); tx_dma_in_progress = 0; + + if (IS_ENABLED(CONFIG_PRESERVE_LOGS)) + tx_checksum = uart_buffer_calc_checksum(); } /* Disable DMA-done interrupt if nothing to send */ @@ -147,6 +172,9 @@ void uart_process_output(void) while (uart_tx_ready() && (tx_buf_head != tx_buf_tail)) { uart_write_char(tx_buf[tx_buf_tail]); tx_buf_tail = TX_BUF_NEXT(tx_buf_tail); + + if (IS_ENABLED(CONFIG_PRESERVE_LOGS)) + tx_checksum = uart_buffer_calc_checksum(); } /* If output buffer is empty, disable transmit interrupt */ diff --git a/core/cortex-m0/ec.lds.S b/core/cortex-m0/ec.lds.S index 42e0b2e034..953433459a 100644 --- a/core/cortex-m0/ec.lds.S +++ b/core/cortex-m0/ec.lds.S @@ -191,16 +191,36 @@ SECTIONS . = ALIGN(4); } > FLASH __data_lma_start = . ; - - .bss : { + .vtable : { /* - * Vector table must be at the beginning of bss section. The vector + * Vector table must be at the base of SRAM. The vector * table section contains a RAM copy of the vector table used on * STM chips for relocating the vector table. */ . = ALIGN(8); - __bss_start = .; *(.bss.vector_table) + . = ALIGN(8); + } > IRAM + +#ifdef CONFIG_PRESERVE_LOGS + .preserve_logs(NOLOAD) : { + /* + * The size of the vector table is fixed. Thus, the address of + * the preserved logs is also fixed. + */ + . = ALIGN(8); + *(SORT(.preserved_logs.*)) + . = ALIGN(8); + __preserved_logs_end = .; + } > IRAM + + ASSERT((SIZEOF(.vtable) + SIZEOF(.preserve_logs) + CONFIG_RAM_BASE) == + __preserved_logs_end, "preserve_logs must be right after vtable") +#endif + + .bss : { + . = ALIGN(8); + __bss_start = .; /* Stacks must be 64-bit aligned */ . = ALIGN(8); *(.bss.system_stack) diff --git a/include/chipset.h b/include/chipset.h index bb0d7b4943..05eeb844a1 100644 --- a/include/chipset.h +++ b/include/chipset.h @@ -263,3 +263,8 @@ static inline void report_ap_reset(enum chipset_shutdown_reason reason) { } #endif /* !CONFIG_CMD_AP_RESET_LOG */ #endif /* __CROS_EC_CHIPSET_H */ + +/** + * Initialize reset logs and next reset log. + */ +void init_reset_log(void); diff --git a/include/config.h b/include/config.h index 377f89d603..5bb89a7a46 100644 --- a/include/config.h +++ b/include/config.h @@ -3525,6 +3525,15 @@ */ #undef CONFIG_UART_PAD_SWITCH +/** + * This will only be used for Kukui and cortex-m0. Preserve EC reset logs and + * console logs on SRAM so that the logs will be preserved after EC shutting + * down or sysjumped. It will keep the contents across EC resets, so we have + * more information about system states. The contents on SRAM will be cleared + * when checksum or sanity check fails. + */ +#undef CONFIG_PRESERVE_LOGS + /* * UART receive buffer size in bytes. Must be a power of 2 for macros in * common/uart_buffering.c to work properly. Must be larger than diff --git a/include/link_defs.h b/include/link_defs.h index 28ea0113e1..5ea500516f 100644 --- a/include/link_defs.h +++ b/include/link_defs.h @@ -134,3 +134,10 @@ extern void *__dram_bss_end; #endif #endif /* __CROS_EC_LINK_DEFS_H */ + +#ifdef CONFIG_PRESERVE_LOGS +#define __preserved_logs(name) \ + __attribute__((section(".preserved_logs." STRINGIFY(name)))) +#else +#define __preserved_logs(name) +#endif diff --git a/include/uart.h b/include/uart.h index d5493544c2..66561b09a7 100644 --- a/include/uart.h +++ b/include/uart.h @@ -352,3 +352,8 @@ int uart_console_read_buffer(uint8_t type, uint16_t *write_count); #endif /* __CROS_EC_UART_H */ + +/** + * Initialize tx buffer head and tail + */ +void uart_init_buffer(void); diff --git a/include/util.h b/include/util.h index 04acffd988..60bb00510a 100644 --- a/include/util.h +++ b/include/util.h @@ -55,6 +55,9 @@ extern "C" { /* True of x is a power of two */ #define POWER_OF_TWO(x) ((x) && !((x) & ((x) - 1))) +/* Macro to check if the value is in range */ +#define IN_RANGE(x, min, max) ((x) >= (min) && (x) < (max)) + /* * macros for integer division with various rounding variants * default integer division rounds down. |