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 */