From ccb151d013d429337a1bb07adfdb55469f3543ba Mon Sep 17 00:00:00 2001 From: Randall Spangler Date: Wed, 6 Sep 2017 14:28:05 -0700 Subject: [PATCH] cr50: Defragment code For historical reasons, CCD, reset, and power button control were scattered around several files. Consolidate the code in more sensible (in retrospect) places. No functional changes, just moving code. BUG=none BRANCH=cr50 TEST=make buildall; boot cr50 Change-Id: Ic381a5a5d0627753cc771189aa377e88b81b155e Signed-off-by: Randall Spangler Reviewed-on: https://chromium-review.googlesource.com/653766 Reviewed-by: Mary Ruthven --- board/cr50/ap_state.c | 1 + board/cr50/board.c | 78 +++++++++++++++++- board/cr50/build.mk | 2 +- board/cr50/ec_state.c | 3 +- board/cr50/power_button.c | 118 ++++++++++++++++++++++++++ board/cr50/rdd.c | 114 ++------------------------ board/cr50/usb_i2c.c | 1 + board/cr50/usb_spi.c | 2 +- board/cr50/wp.c | 84 +------------------ chip/g/usb_spi.c | 2 +- common/ccd_config.c | 2 +- include/case_closed_debug.h | 152 ---------------------------------- include/ccd_config.h | 159 ++++++++++++++++++++++++++++++++++++ 13 files changed, 370 insertions(+), 348 deletions(-) create mode 100644 board/cr50/power_button.c create mode 100644 include/ccd_config.h diff --git a/board/cr50/ap_state.c b/board/cr50/ap_state.c index 0a42e9a41a..e9ddea5640 100644 --- a/board/cr50/ap_state.c +++ b/board/cr50/ap_state.c @@ -4,6 +4,7 @@ * * AP state machine */ +#include "ccd_config.h" #include "common.h" #include "console.h" #include "gpio.h" diff --git a/board/cr50/board.c b/board/cr50/board.c index 238ee2eea5..1cc92e56b3 100644 --- a/board/cr50/board.c +++ b/board/cr50/board.c @@ -3,7 +3,7 @@ * found in the LICENSE file. */ #include "board_id.h" -#include "case_closed_debug.h" +#include "ccd_config.h" #include "clock.h" #include "common.h" #include "console.h" @@ -915,6 +915,48 @@ void board_reboot_ap(void) deassert_sys_rst(); } +/** + * Console command to toggle system (AP) reset + */ +static int command_sys_rst(int argc, char **argv) +{ + int val; + char *e; + int ms = 20; + + if (argc > 1) { + if (!ccd_is_cap_enabled(CCD_CAP_REBOOT_EC_AP)) + return EC_ERROR_ACCESS_DENIED; + + if (!strcasecmp("pulse", argv[1])) { + if (argc == 3) { + ms = strtoi(argv[2], &e, 0); + if (*e) + return EC_ERROR_PARAM2; + } + ccprintf("Pulsing AP reset for %dms\n", ms); + assert_sys_rst(); + msleep(ms); + deassert_sys_rst(); + } else if (parse_bool(argv[1], &val)) { + if (val) + assert_sys_rst(); + else + deassert_sys_rst(); + } else + return EC_ERROR_PARAM1; + } + + ccprintf("SYS_RST_L is %s\n", is_sys_rst_asserted() ? + "asserted" : "deasserted"); + + return EC_SUCCESS; + +} +DECLARE_SAFE_CONSOLE_COMMAND(sysrst, command_sys_rst, + "[pulse [time] | ]", + "Assert/deassert SYS_RST_L to reset the AP"); + void assert_ec_rst(void) { GWRITE(RBOX, ASSERT_EC_RST, 1); @@ -929,6 +971,40 @@ int is_ec_rst_asserted(void) return GREAD(RBOX, ASSERT_EC_RST); } +/** + * Console command to toggle EC reset + */ +static int command_ec_rst(int argc, char **argv) +{ + int val; + + if (argc > 1) { + if (!ccd_is_cap_enabled(CCD_CAP_REBOOT_EC_AP)) + return EC_ERROR_ACCESS_DENIED; + + if (!strcasecmp("pulse", argv[1])) { + ccprintf("Pulsing EC reset\n"); + assert_ec_rst(); + usleep(200); + deassert_ec_rst(); + } else if (parse_bool(argv[1], &val)) { + if (val) + assert_ec_rst(); + else + deassert_ec_rst(); + } else + return EC_ERROR_PARAM1; + } + + ccprintf("EC_RST_L is %s\n", is_ec_rst_asserted() ? + "asserted" : "deasserted"); + + return EC_SUCCESS; +} +DECLARE_SAFE_CONSOLE_COMMAND(ecrst, command_ec_rst, + "[pulse | ]", + "Assert/deassert EC_RST_L to reset the EC (and AP)"); + /* * This function duplicates some of the functionality in chip/g/gpio.c in order * to configure a given strap pin to be either a low gpio output, a gpio input diff --git a/board/cr50/build.mk b/board/cr50/build.mk index d6b40c294e..15e1f1f2a3 100644 --- a/board/cr50/build.mk +++ b/board/cr50/build.mk @@ -29,7 +29,7 @@ dirs-y += chip/$(CHIP)/dcrypto dirs-y += $(BDIR)/tpm2 # Objects that we need to build -board-y = board.o ap_state.o ec_state.o servo_state.o +board-y = board.o ap_state.o ec_state.o power_button.o servo_state.o board-${CONFIG_RDD} += rdd.o board-${CONFIG_USB_SPI} += usb_spi.o board-${CONFIG_USB_I2C} += usb_i2c.o diff --git a/board/cr50/ec_state.c b/board/cr50/ec_state.c index 4fe8400568..a208cbfd2c 100644 --- a/board/cr50/ec_state.c +++ b/board/cr50/ec_state.c @@ -2,8 +2,9 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * - * EC detect state machine. + * EC state machine */ +#include "ccd_config.h" #include "common.h" #include "console.h" #include "gpio.h" diff --git a/board/cr50/power_button.c b/board/cr50/power_button.c new file mode 100644 index 0000000000..bf178e893f --- /dev/null +++ b/board/cr50/power_button.c @@ -0,0 +1,118 @@ +/* Copyright 2017 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 "console.h" +#include "gpio.h" +#include "hooks.h" +#include "physical_presence.h" +#include "rbox.h" +#include "registers.h" +#include "system.h" +#include "system_chip.h" +#include "task.h" +#include "timer.h" + +#define CPRINTS(format, args...) cprints(CC_RBOX, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_RBOX, format, ## args) + +/** + * Enable/disable power button interrupt. + * + * @param enable Enable (!=0) or disable (==0) + */ +static void power_button_enable_interrupt(int enable) +{ + if (enable) { + /* Clear any leftover power button interrupts */ + GWRITE_FIELD(RBOX, INT_STATE, INTR_PWRB_IN_FED, 1); + + /* Enable power button interrupt */ + GWRITE_FIELD(RBOX, INT_ENABLE, INTR_PWRB_IN_FED, 1); + task_enable_irq(GC_IRQNUM_RBOX0_INTR_PWRB_IN_FED_INT); + } else { + GWRITE_FIELD(RBOX, INT_ENABLE, INTR_PWRB_IN_FED, 0); + task_disable_irq(GC_IRQNUM_RBOX0_INTR_PWRB_IN_FED_INT); + } +} + +static void power_button_handler(void) +{ + CPRINTS("power button pressed"); + + if (physical_detect_press() != EC_SUCCESS) { + /* Not consumed by physical detect */ +#ifdef CONFIG_U2F + /* Track last power button press for U2F */ + power_button_record(); +#endif + } + + GWRITE_FIELD(RBOX, INT_STATE, INTR_PWRB_IN_FED, 1); +} +DECLARE_IRQ(GC_IRQNUM_RBOX0_INTR_PWRB_IN_FED_INT, power_button_handler, 1); + +#ifdef CONFIG_U2F +static void power_button_init(void) +{ + /* + * Enable power button interrupts all the time for U2F. + * + * Ideally U2F should only enable physical presence after the start of + * a U2F request (using atomic operations for the PP enable mask so it + * plays nicely with CCD config), but that doesn't happen yet. + */ + power_button_enable_interrupt(1); +} +DECLARE_HOOK(HOOK_INIT, power_button_init, HOOK_PRIO_DEFAULT); +#endif /* CONFIG_U2F */ + +void board_physical_presence_enable(int enable) +{ +#ifndef CONFIG_U2F + /* Enable/disable power button interrupts */ + power_button_enable_interrupt(enable); +#endif + + /* Stay awake while we're doing this, just in case. */ + if (enable) + disable_sleep(SLEEP_MASK_PHYSICAL_PRESENCE); + else + enable_sleep(SLEEP_MASK_PHYSICAL_PRESENCE); +} + +static int command_powerbtn(int argc, char **argv) +{ + char *e; + int ms = 200; + + if (argc > 1) { + if (!strcasecmp("pulse", argv[1])) { + if (argc == 3) { + ms = strtoi(argv[2], &e, 0); + if (*e) + return EC_ERROR_PARAM2; + } + + ccprintf("Force %dms power button press\n", ms); + + rbox_powerbtn_press(); + msleep(ms); + rbox_powerbtn_release(); + } else if (!strcasecmp("press", argv[1])) { + rbox_powerbtn_press(); + } else if (!strcasecmp("release", argv[1])) { + rbox_powerbtn_release(); + } else + return EC_ERROR_PARAM1; + } + + ccprintf("powerbtn: %s\n", + rbox_powerbtn_override_is_enabled() ? "forced press" : + rbox_powerbtn_is_pressed() ? "pressed\n" : "released\n"); + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(powerbtn, command_powerbtn, + "[pulse [ms] | press | release]", + "get/set the state of the power button"); diff --git a/board/cr50/rdd.c b/board/cr50/rdd.c index 037d5bbc7d..26a3f2b507 100644 --- a/board/cr50/rdd.c +++ b/board/cr50/rdd.c @@ -3,7 +3,8 @@ * found in the LICENSE file. */ -#include "case_closed_debug.h" +#include "case_closed_debug.h" /* For ccd_ext_is_enabled() */ +#include "ccd_config.h" #include "console.h" #include "gpio.h" #include "hooks.h" @@ -126,6 +127,11 @@ enum ccd_state_flag { CCD_ENABLE_SPI = (1 << 6), }; +int console_is_restricted(void) +{ + return !ccd_is_cap_enabled(CCD_CAP_GSC_RESTRICTED_CONSOLE); +} + /** * Return the currently enabled state flags (see enum ccd_state_flag). */ @@ -347,8 +353,6 @@ static void ccd_ext_detect(void) } DECLARE_HOOK(HOOK_SECOND, ccd_ext_detect, HOOK_PRIO_DEFAULT); -/*****************************************************************************/ - static int command_ccd_state(int argc, char **argv) { print_ap_state(); @@ -369,107 +373,3 @@ DECLARE_CONSOLE_COMMAND(ccdstate, command_ccd_state, "", "Print the case closed debug device state"); -static int command_sys_rst(int argc, char **argv) -{ - int val; - char *e; - int ms = 20; - - if (argc > 1) { - if (!ccd_is_cap_enabled(CCD_CAP_REBOOT_EC_AP)) - return EC_ERROR_ACCESS_DENIED; - - if (!strcasecmp("pulse", argv[1])) { - if (argc == 3) { - ms = strtoi(argv[2], &e, 0); - if (*e) - return EC_ERROR_PARAM2; - } - ccprintf("Pulsing AP reset for %dms\n", ms); - assert_sys_rst(); - msleep(ms); - deassert_sys_rst(); - } else if (parse_bool(argv[1], &val)) { - if (val) - assert_sys_rst(); - else - deassert_sys_rst(); - } else - return EC_ERROR_PARAM1; - } - - ccprintf("SYS_RST_L is %s\n", is_sys_rst_asserted() ? - "asserted" : "deasserted"); - - return EC_SUCCESS; - -} -DECLARE_SAFE_CONSOLE_COMMAND(sysrst, command_sys_rst, - "[pulse [time] | ]", - "Assert/deassert SYS_RST_L to reset the AP"); - -static int command_ec_rst(int argc, char **argv) -{ - int val; - - if (argc > 1) { - if (!ccd_is_cap_enabled(CCD_CAP_REBOOT_EC_AP)) - return EC_ERROR_ACCESS_DENIED; - - if (!strcasecmp("pulse", argv[1])) { - ccprintf("Pulsing EC reset\n"); - assert_ec_rst(); - usleep(200); - deassert_ec_rst(); - } else if (parse_bool(argv[1], &val)) { - if (val) - assert_ec_rst(); - else - deassert_ec_rst(); - } else - return EC_ERROR_PARAM1; - } - - ccprintf("EC_RST_L is %s\n", is_ec_rst_asserted() ? - "asserted" : "deasserted"); - - return EC_SUCCESS; -} -DECLARE_SAFE_CONSOLE_COMMAND(ecrst, command_ec_rst, - "[pulse | ]", - "Assert/deassert EC_RST_L to reset the EC (and AP)"); - -static int command_powerbtn(int argc, char **argv) -{ - char *e; - int ms = 200; - - if (argc > 1) { - if (!strcasecmp("pulse", argv[1])) { - if (argc == 3) { - ms = strtoi(argv[2], &e, 0); - if (*e) - return EC_ERROR_PARAM2; - } - - ccprintf("Force %dms power button press\n", ms); - - rbox_powerbtn_press(); - msleep(ms); - rbox_powerbtn_release(); - } else if (!strcasecmp("press", argv[1])) { - rbox_powerbtn_press(); - } else if (!strcasecmp("release", argv[1])) { - rbox_powerbtn_release(); - } else - return EC_ERROR_PARAM1; - } - - ccprintf("powerbtn: %s\n", - rbox_powerbtn_override_is_enabled() ? "forced press" : - rbox_powerbtn_is_pressed() ? "pressed\n" : "released\n"); - return EC_SUCCESS; -} -DECLARE_CONSOLE_COMMAND(powerbtn, command_powerbtn, - "[pulse [ms] | press | release]", - "get/set the state of the power button"); diff --git a/board/cr50/usb_i2c.c b/board/cr50/usb_i2c.c index 6536e00ca7..1aa18012c3 100644 --- a/board/cr50/usb_i2c.c +++ b/board/cr50/usb_i2c.c @@ -4,6 +4,7 @@ */ #include "case_closed_debug.h" +#include "ccd_config.h" #include "console.h" #include "gpio.h" #include "hooks.h" diff --git a/board/cr50/usb_spi.c b/board/cr50/usb_spi.c index 1fa67fbdf5..31b900109f 100644 --- a/board/cr50/usb_spi.c +++ b/board/cr50/usb_spi.c @@ -3,7 +3,7 @@ * found in the LICENSE file. */ -#include "case_closed_debug.h" +#include "ccd_config.h" #include "console.h" #include "gpio.h" #include "hooks.h" diff --git a/board/cr50/wp.c b/board/cr50/wp.c index 74a44f8ee0..0edb681fcd 100644 --- a/board/cr50/wp.c +++ b/board/cr50/wp.c @@ -3,22 +3,16 @@ * found in the LICENSE file. */ -#include "common.h" -#include "case_closed_debug.h" +#include "ccd_config.h" #include "console.h" #include "crc8.h" #include "extension.h" #include "gpio.h" #include "hooks.h" -#include "nvmem.h" -#include "nvmem_vars.h" -#include "physical_presence.h" #include "registers.h" #include "scratch_reg1.h" #include "system.h" #include "system_chip.h" -#include "task.h" -#include "timer.h" #include "tpm_nvmem_read.h" #include "tpm_registers.h" #include "util.h" @@ -320,82 +314,6 @@ int board_fwmp_allows_unlock(void) #endif } -/****************************************************************************/ -/* Console control */ - -int console_is_restricted(void) -{ - return !ccd_is_cap_enabled(CCD_CAP_GSC_RESTRICTED_CONSOLE); -} - -/****************************************************************************/ -/* Stuff for the unlock sequence */ - -/** - * Enable/disable power button interrupt. - * - * @param enable Enable (!=0) or disable (==0) - */ -static void power_button_enable_interrupt(int enable) -{ - if (enable) { - /* Clear any leftover power button interrupts */ - GWRITE_FIELD(RBOX, INT_STATE, INTR_PWRB_IN_FED, 1); - - /* Enable power button interrupt */ - GWRITE_FIELD(RBOX, INT_ENABLE, INTR_PWRB_IN_FED, 1); - task_enable_irq(GC_IRQNUM_RBOX0_INTR_PWRB_IN_FED_INT); - } else { - GWRITE_FIELD(RBOX, INT_ENABLE, INTR_PWRB_IN_FED, 0); - task_disable_irq(GC_IRQNUM_RBOX0_INTR_PWRB_IN_FED_INT); - } -} - -static void power_button_handler(void) -{ - CPRINTS("power button pressed"); - - if (physical_detect_press() != EC_SUCCESS) { - /* Not consumed by physical detect */ -#ifdef CONFIG_U2F - /* Track last power button press for U2F */ - power_button_record(); -#endif - } - - GWRITE_FIELD(RBOX, INT_STATE, INTR_PWRB_IN_FED, 1); -} -DECLARE_IRQ(GC_IRQNUM_RBOX0_INTR_PWRB_IN_FED_INT, power_button_handler, 1); - -#ifdef CONFIG_U2F -static void power_button_init(void) -{ - /* - * Enable power button interrupts all the time for U2F. - * - * Ideally U2F should only enable physical presence after the start of - * a U2F request (using atomic operations for the PP enable mask so it - * plays nicely with CCD config), but that doesn't happen yet. - */ - power_button_enable_interrupt(1); -} -DECLARE_HOOK(HOOK_INIT, power_button_init, HOOK_PRIO_DEFAULT); -#endif /* CONFIG_U2F */ - -void board_physical_presence_enable(int enable) -{ -#ifndef CONFIG_U2F - /* Enable/disable power button interrupts */ - power_button_enable_interrupt(enable); -#endif - - /* Stay awake while we're doing this, just in case. */ - if (enable) - disable_sleep(SLEEP_MASK_PHYSICAL_PRESENCE); - else - enable_sleep(SLEEP_MASK_PHYSICAL_PRESENCE); -} - /****************************************************************************/ /* TPM vendor-specific commands */ diff --git a/chip/g/usb_spi.c b/chip/g/usb_spi.c index 140f3c8a28..34e23bc4c5 100644 --- a/chip/g/usb_spi.c +++ b/chip/g/usb_spi.c @@ -3,7 +3,7 @@ * found in the LICENSE file. */ -#include "case_closed_debug.h" +#include "ccd_config.h" #include "common.h" #include "link_defs.h" #include "gpio.h" diff --git a/common/ccd_config.c b/common/ccd_config.c index bf8efe339e..3849cddee7 100644 --- a/common/ccd_config.c +++ b/common/ccd_config.c @@ -5,7 +5,7 @@ * Case Closed Debug configuration */ -#include "case_closed_debug.h" +#include "ccd_config.h" #include "common.h" #include "console.h" #include "cryptoc/sha256.h" diff --git a/include/case_closed_debug.h b/include/case_closed_debug.h index eb441327a7..4cab77165c 100644 --- a/include/case_closed_debug.h +++ b/include/case_closed_debug.h @@ -48,156 +48,4 @@ enum ccd_mode ccd_get_mode(void); */ int ccd_ext_is_enabled(void); -/******************************************************************************/ -/* New CCD "V1" configuration. Eventually this will supersede the above code */ - -/* Case-closed debugging state */ -enum ccd_state { - CCD_STATE_LOCKED = 0, - CCD_STATE_UNLOCKED, - CCD_STATE_OPENED, - - /* Number of CCD states */ - CCD_STATE_COUNT -}; - -/* Flags */ -enum ccd_flag { - /* Flags that can only be set internally; fill from bottom up */ - - /* - * Test lab mode is enabled. This MUST be in the first byte so that - * it's in a constant position across all versions of CCD config. - * - * Note: This is used internally by CCD config. Do NOT test this - * to control other things; use capabilities for those. - */ - CCD_FLAG_TEST_LAB = (1 << 0), - - /* - * What state were we in when the password was set? - * (0=opened, 1=unlocked) - */ - CCD_FLAG_PASSWORD_SET_WHEN_UNLOCKED = (1 << 1), - - /* (flags in the middle are unused) */ - - /* Flags that can be set via ccd_set_flags(); fill from top down */ - - /* Override write protect at boot */ - CCD_FLAG_OVERRIDE_WP_AT_BOOT = (1 << 22), - - /* - * If overriding WP at boot, set it to what value - * (0=disabled, 1=enabled) - */ - CCD_FLAG_OVERRIDE_WP_STATE_ENABLED = (1 << 23), -}; - -/* Capabilities */ -enum ccd_capability { - /* UARTs to/from AP and EC */ - CCD_CAP_GSC_RX_AP_TX = 0, - CCD_CAP_GSC_TX_AP_RX = 1, - CCD_CAP_GSC_RX_EC_TX = 2, - CCD_CAP_GSC_TX_EC_RX = 3, - - /* Access to AP SPI flash */ - CCD_CAP_AP_FLASH = 4, - - /* Access to EC flash (SPI or internal) */ - CCD_CAP_EC_FLASH = 5, - - /* Override WP temporarily or at boot */ - CCD_CAP_OVERRIDE_WP = 6, - - /* Reboot EC or AP */ - CCD_CAP_REBOOT_EC_AP = 7, - - /* GSC restricted console commands */ - CCD_CAP_GSC_RESTRICTED_CONSOLE = 8, - - /* Allow ccd-unlock or ccd-open without AP reboot */ - CCD_CAP_UNLOCK_WITHOUT_AP_REBOOT = 9, - - /* Allow ccd-unlock or ccd-open without short physical presence */ - CCD_CAP_UNLOCK_WITHOUT_SHORT_PP = 10, - - /* Allow ccd-open without wiping TPM data */ - CCD_CAP_OPEN_WITHOUT_TPM_WIPE = 11, - - /* Allow ccd-open without long physical presence */ - CCD_CAP_OPEN_WITHOUT_LONG_PP = 12, - - /* Allow removing the battery to bypass physical presence requirement */ - CCD_CAP_REMOVE_BATTERY_BYPASSES_PP = 13, - - /* Allow GSC firmware update without wiping TPM data */ - CCD_CAP_GSC_FW_UPDATE_WITHOUT_TPM_WIPE = 14, - - /* Access to I2C via USB */ - CCD_CAP_I2C = 15, - - /* Number of currently defined capabilities */ - CCD_CAP_COUNT -}; - -/** - * Initialize CCD configuration at boot. - * - * This must be called before any command which gets/sets the configuration. - * - * @param state Initial case-closed debugging state. This should be - * CCD_STATE_LOCKED unless this is a debug build, or if - * a previous value is being restored after a low-power - * resume. - */ -void ccd_config_init(enum ccd_state state); - -/** - * Get a single CCD flag. - * - * @param flag Flag to get - * @return 1 if flag is set, 0 if flag is clear - */ -int ccd_get_flag(enum ccd_flag flag); - -/** - * Set a single CCD flag. - * - * @param flag Flag to set - * @param value New value for flag (0=clear, non-zero=set) - * @return EC_SUCCESS or non-zero error code. - */ -int ccd_set_flag(enum ccd_flag flag, int value); - -/** - * Check if a CCD capability is enabled in the current CCD mode. - * - * @param cap Capability to check - * @return 1 if capability is enabled, 0 if disabled - */ -int ccd_is_cap_enabled(enum ccd_capability cap); - -/** - * Get the current CCD state. - * - * This is intended for use by the board if it needs to back up the CCD state - * across low-power states and then restore it when calling ccd_config_init(). - * Do NOT use this to gate debug capabilities; use ccd_is_cap_enabled() or - * ccd_get_flag() instead. - * - * @return The current CCD state. - */ -enum ccd_state ccd_get_state(void); - -/** - * Force CCD disabled. - * - * This should be called if security checks fail and for some reason the board - * can't immediately reboot. It locks CCD and disables all CCD capabilities - * until reboot. - */ -void ccd_disable(void); - #endif /* __CROS_EC_CASE_CLOSED_DEBUG_H */ diff --git a/include/ccd_config.h b/include/ccd_config.h new file mode 100644 index 0000000000..333f4552b7 --- /dev/null +++ b/include/ccd_config.h @@ -0,0 +1,159 @@ +/* Copyright 2017 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. + * + * Case Closed Debugging configuration + */ +#ifndef __CROS_EC_CCD_CONFIG_H +#define __CROS_EC_CCD_CONFIG_H + +/* Case-closed debugging state */ +enum ccd_state { + CCD_STATE_LOCKED = 0, + CCD_STATE_UNLOCKED, + CCD_STATE_OPENED, + + /* Number of CCD states */ + CCD_STATE_COUNT +}; + +/* Flags */ +enum ccd_flag { + /* Flags that can only be set internally; fill from bottom up */ + + /* + * Test lab mode is enabled. This MUST be in the first byte so that + * it's in a constant position across all versions of CCD config. + * + * Note: This is used internally by CCD config. Do NOT test this + * to control other things; use capabilities for those. + */ + CCD_FLAG_TEST_LAB = (1 << 0), + + /* + * What state were we in when the password was set? + * (0=opened, 1=unlocked) + */ + CCD_FLAG_PASSWORD_SET_WHEN_UNLOCKED = (1 << 1), + + /* (flags in the middle are unused) */ + + /* Flags that can be set via ccd_set_flags(); fill from top down */ + + /* Override write protect at boot */ + CCD_FLAG_OVERRIDE_WP_AT_BOOT = (1 << 22), + + /* + * If overriding WP at boot, set it to what value + * (0=disabled, 1=enabled) + */ + CCD_FLAG_OVERRIDE_WP_STATE_ENABLED = (1 << 23), +}; + +/* Capabilities */ +enum ccd_capability { + /* UARTs to/from AP and EC */ + CCD_CAP_GSC_RX_AP_TX = 0, + CCD_CAP_GSC_TX_AP_RX = 1, + CCD_CAP_GSC_RX_EC_TX = 2, + CCD_CAP_GSC_TX_EC_RX = 3, + + /* Access to AP SPI flash */ + CCD_CAP_AP_FLASH = 4, + + /* Access to EC flash (SPI or internal) */ + CCD_CAP_EC_FLASH = 5, + + /* Override WP temporarily or at boot */ + CCD_CAP_OVERRIDE_WP = 6, + + /* Reboot EC or AP */ + CCD_CAP_REBOOT_EC_AP = 7, + + /* GSC restricted console commands */ + CCD_CAP_GSC_RESTRICTED_CONSOLE = 8, + + /* Allow ccd-unlock or ccd-open without AP reboot */ + CCD_CAP_UNLOCK_WITHOUT_AP_REBOOT = 9, + + /* Allow ccd-unlock or ccd-open without short physical presence */ + CCD_CAP_UNLOCK_WITHOUT_SHORT_PP = 10, + + /* Allow ccd-open without wiping TPM data */ + CCD_CAP_OPEN_WITHOUT_TPM_WIPE = 11, + + /* Allow ccd-open without long physical presence */ + CCD_CAP_OPEN_WITHOUT_LONG_PP = 12, + + /* Allow removing the battery to bypass physical presence requirement */ + CCD_CAP_REMOVE_BATTERY_BYPASSES_PP = 13, + + /* Allow GSC firmware update without wiping TPM data */ + CCD_CAP_GSC_FW_UPDATE_WITHOUT_TPM_WIPE = 14, + + /* Access to I2C via USB */ + CCD_CAP_I2C = 15, + + /* Number of currently defined capabilities */ + CCD_CAP_COUNT +}; + +/** + * Initialize CCD configuration at boot. + * + * This must be called before any command which gets/sets the configuration. + * + * @param state Initial case-closed debugging state. This should be + * CCD_STATE_LOCKED unless this is a debug build, or if + * a previous value is being restored after a low-power + * resume. + */ +void ccd_config_init(enum ccd_state state); + +/** + * Get a single CCD flag. + * + * @param flag Flag to get + * @return 1 if flag is set, 0 if flag is clear + */ +int ccd_get_flag(enum ccd_flag flag); + +/** + * Set a single CCD flag. + * + * @param flag Flag to set + * @param value New value for flag (0=clear, non-zero=set) + * @return EC_SUCCESS or non-zero error code. + */ +int ccd_set_flag(enum ccd_flag flag, int value); + +/** + * Check if a CCD capability is enabled in the current CCD mode. + * + * @param cap Capability to check + * @return 1 if capability is enabled, 0 if disabled + */ +int ccd_is_cap_enabled(enum ccd_capability cap); + +/** + * Get the current CCD state. + * + * This is intended for use by the board if it needs to back up the CCD state + * across low-power states and then restore it when calling ccd_config_init(). + * Do NOT use this to gate debug capabilities; use ccd_is_cap_enabled() or + * ccd_get_flag() instead. + * + * @return The current CCD state. + */ +enum ccd_state ccd_get_state(void); + +/** + * Force CCD disabled. + * + * This should be called if security checks fail and for some reason the board + * can't immediately reboot. It locks CCD and disables all CCD capabilities + * until reboot. + */ +void ccd_disable(void); + +#endif /* __CROS_EC_CCD_CONFIG_H */