diff options
author | Hung-Te Lin <hungte@chromium.org> | 2016-04-07 12:21:03 +0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-04-12 05:49:26 -0700 |
commit | aee6bd69fefac653cfc4a5679eb387d7c3280d14 (patch) | |
tree | f2756467870078563b99904eebf32e6d93211b1f | |
parent | eb0c8cc39bb268a7dc88ed616a564f4d46f77a2c (diff) | |
download | vboot-aee6bd69fefac653cfc4a5679eb387d7c3280d14.tar.gz |
Support doing battery cut-off in firmware stage.
Add a new crossystem value "battery_cutoff_request" to indicate that
next reboot should cut-off battery and shutdown during firmware stage.
This request is primarily for factories to ship devices in an safe
state. Previously we have done same thing by running "ectool battery-cutoff"
but that creates a problem which "ectool" (and the one to request for
cut-off) must live in developer mode while the device must be shipped
in normal mode. The mode transition was solved by setting
"disable_dev_request=1", but that flag is may get lost on x86 systems
(having NV storage in CMOS) when the battery is cut-off .
From the experience from Ryu, such settings (dev mode transition and
battery cut-off) should be done together inside firmware execution so we
can create a new flag, battery_cutoff_request, to finalize device
properly.
BRANCH=none
BUG=chromium:601705
TEST=emerge-chell depthcharge vboot_reference chromeos-bootimage
crossystem battery_cutoff_request=1
# Unplug AC adapter
reboot
# See device rebooted and then shutdown immediately.
# Press power button and system won't boot.
# Attach AC adapter and now system boots.
CQ-DEPEND=CL:337596,CL:338193
Change-Id: I73ccae15b337cd65786106646546c67c155b8fa6
Reviewed-on: https://chromium-review.googlesource.com/337602
Commit-Ready: Hung-Te Lin <hungte@chromium.org>
Tested-by: Hung-Te Lin <hungte@chromium.org>
Reviewed-by: Duncan Laurie <dlaurie@chromium.org>
-rw-r--r-- | firmware/2lib/2nvstorage.c | 6 | ||||
-rw-r--r-- | firmware/2lib/include/2nvstorage.h | 2 | ||||
-rw-r--r-- | firmware/2lib/include/2nvstorage_fields.h | 3 | ||||
-rw-r--r-- | firmware/include/vboot_api.h | 5 | ||||
-rw-r--r-- | firmware/include/vboot_nvstorage.h | 5 | ||||
-rw-r--r-- | firmware/lib/vboot_api_kernel.c | 12 | ||||
-rw-r--r-- | firmware/lib/vboot_nvstorage.c | 13 | ||||
-rw-r--r-- | firmware/stub/vboot_api_stub.c | 5 | ||||
-rw-r--r-- | host/lib/crossystem.c | 4 | ||||
-rw-r--r-- | utility/crossystem.c | 2 |
10 files changed, 55 insertions, 2 deletions
diff --git a/firmware/2lib/2nvstorage.c b/firmware/2lib/2nvstorage.c index 3e2a8740..b40bbe78 100644 --- a/firmware/2lib/2nvstorage.c +++ b/firmware/2lib/2nvstorage.c @@ -172,6 +172,9 @@ uint32_t vb2_nv_get(struct vb2_context *ctx, enum vb2_nv_param param) case VB2_NV_TRY_RO_SYNC: return GETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_TRY_RO_SYNC); + + case VB2_NV_BATTERY_CUTOFF_REQUEST: + return GETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_BATTERY_CUTOFF); } /* @@ -350,6 +353,9 @@ void vb2_nv_set(struct vb2_context *ctx, SETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_TRY_RO_SYNC); break; + case VB2_NV_BATTERY_CUTOFF_REQUEST: + SETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_BATTERY_CUTOFF); + break; } /* diff --git a/firmware/2lib/include/2nvstorage.h b/firmware/2lib/include/2nvstorage.h index 5c958c76..66a5fdf1 100644 --- a/firmware/2lib/include/2nvstorage.h +++ b/firmware/2lib/include/2nvstorage.h @@ -96,6 +96,8 @@ enum vb2_nv_param { VB2_NV_BOOT_ON_AC_DETECT, /* Try to update the EC-RO image after updating the EC-RW image(0=no, 1=yes). */ VB2_NV_TRY_RO_SYNC, + /* Cut off battery and shutdown on next boot. */ + VB2_NV_BATTERY_CUTOFF_REQUEST, }; /* Set default boot in developer mode */ diff --git a/firmware/2lib/include/2nvstorage_fields.h b/firmware/2lib/include/2nvstorage_fields.h index 9ec3d884..018bdeb7 100644 --- a/firmware/2lib/include/2nvstorage_fields.h +++ b/firmware/2lib/include/2nvstorage_fields.h @@ -70,9 +70,10 @@ enum vb2_nv_offset { #define VB2_NV_TPM_CLEAR_OWNER_DONE 0x02 #define VB2_NV_TPM_REBOOTED 0x04 -/* Fields in VB2_NV_OFFS_MISC (unused = 0xf8) */ +/* Fields in VB2_NV_OFFS_MISC (unused = 0xf0) */ #define VB2_NV_MISC_UNLOCK_FASTBOOT 0x01 #define VB2_NV_MISC_BOOT_ON_AC_DETECT 0x02 #define VB2_NV_MISC_TRY_RO_SYNC 0x04 +#define VB2_NV_MISC_BATTERY_CUTOFF 0x08 #endif /* VBOOT_REFERENCE_VBOOT_2NVSTORAGE_FIELDS_H_ */ diff --git a/firmware/include/vboot_api.h b/firmware/include/vboot_api.h index ddc8cc62..5046d2ae 100644 --- a/firmware/include/vboot_api.h +++ b/firmware/include/vboot_api.h @@ -945,6 +945,11 @@ VbError_t VbExEcEnteringMode(int devidx, enum VbEcBootMode_t mode); */ VbError_t VbExEcVbootDone(int in_recovery); +/** + * Request EC to stop discharging and cut-off battery. + */ +VbError_t VbExEcBatteryCutOff(void); + /*****************************************************************************/ /* Misc */ diff --git a/firmware/include/vboot_nvstorage.h b/firmware/include/vboot_nvstorage.h index 91f62cb4..ef78e47a 100644 --- a/firmware/include/vboot_nvstorage.h +++ b/firmware/include/vboot_nvstorage.h @@ -120,7 +120,10 @@ typedef enum VbNvParam { VBNV_BOOT_ON_AC_DETECT, /* Try to update the EC-RO image (0=no, 1=yes). */ VBNV_TRY_RO_SYNC, - + /* + * Finish mode transition (if requested), perform battery cut-off and + * shutdown in next boot. */ + VBNV_BATTERY_CUTOFF_REQUEST, } VbNvParam; /* Set default boot in developer mode */ diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c index fff30561..c3362789 100644 --- a/firmware/lib/vboot_api_kernel.c +++ b/firmware/lib/vboot_api_kernel.c @@ -1082,6 +1082,7 @@ VbError_t VbSelectAndLoadKernel(VbCommonParams *cparams, VbError_t retval = VBERROR_SUCCESS; LoadKernelParams p; uint32_t tpm_status = 0; + uint32_t battery_cutoff = 0; /* Start timer */ shared->timer_vb_select_and_load_kernel_enter = VbExGetTimer(); @@ -1138,6 +1139,17 @@ VbError_t VbSelectAndLoadKernel(VbCommonParams *cparams, if (retval != VBERROR_SUCCESS) goto VbSelectAndLoadKernel_exit; + /* Check if we need to cut-off battery. This must be done after EC + * firmware updating and before kernel started. */ + VbNvGet(&vnc, VBNV_BATTERY_CUTOFF_REQUEST, &battery_cutoff); + if (battery_cutoff) { + VBDEBUG(("Request to cut-off battery\n")); + VbNvSet(&vnc, VBNV_BATTERY_CUTOFF_REQUEST, 0); + VbExEcBatteryCutOff(); + retval = VBERROR_SHUTDOWN_REQUESTED; + goto VbSelectAndLoadKernel_exit; + } + /* Read kernel version from the TPM. Ignore errors in recovery mode. */ tpm_status = RollbackKernelRead(&shared->kernel_version_tpm); if (0 != tpm_status) { diff --git a/firmware/lib/vboot_nvstorage.c b/firmware/lib/vboot_nvstorage.c index d022c5d3..c131f088 100644 --- a/firmware/lib/vboot_nvstorage.c +++ b/firmware/lib/vboot_nvstorage.c @@ -64,6 +64,7 @@ #define MISC_UNLOCK_FASTBOOT 0x01 #define MISC_BOOT_ON_AC_DETECT 0x02 #define MISC_TRY_RO_SYNC 0x04 +#define MISC_BATTERY_CUTOFF_REQUEST 0x08 #define KERNEL_FIELD_OFFSET 11 #define CRC_OFFSET 15 @@ -231,6 +232,11 @@ int VbNvGet(VbNvContext *context, VbNvParam param, uint32_t *dest) *dest = (raw[MISC_OFFSET] & MISC_TRY_RO_SYNC) ? 1 : 0; return 0; + case VBNV_BATTERY_CUTOFF_REQUEST: + *dest = (raw[MISC_OFFSET] & MISC_BATTERY_CUTOFF_REQUEST) + ? 1 : 0; + return 0; + default: return 1; } @@ -456,6 +462,13 @@ int VbNvSet(VbNvContext *context, VbNvParam param, uint32_t value) raw[MISC_OFFSET] &= ~MISC_TRY_RO_SYNC; break; + case VBNV_BATTERY_CUTOFF_REQUEST: + if (value) + raw[MISC_OFFSET] |= MISC_BATTERY_CUTOFF_REQUEST; + else + raw[MISC_OFFSET] &= ~MISC_BATTERY_CUTOFF_REQUEST; + break; + default: return 1; } diff --git a/firmware/stub/vboot_api_stub.c b/firmware/stub/vboot_api_stub.c index 2299a033..7bc4cb86 100644 --- a/firmware/stub/vboot_api_stub.c +++ b/firmware/stub/vboot_api_stub.c @@ -166,6 +166,11 @@ VbError_t VbExEcVbootDone(int in_recovery) return VBERROR_SUCCESS; } +VbError_t VbExEcBatteryCutOff(void) +{ + return VBERROR_SUCCESS; +} + enum VbEcBootMode_t VbGetMode(void) { return vboot_mode; diff --git a/host/lib/crossystem.c b/host/lib/crossystem.c index bcbf4dd4..7c51927e 100644 --- a/host/lib/crossystem.c +++ b/host/lib/crossystem.c @@ -551,6 +551,8 @@ int VbGetSystemPropertyInt(const char* name) { value = VbGetNvStorage(VBNV_BOOT_ON_AC_DETECT); } else if (!strcasecmp(name, "try_ro_sync")) { value = VbGetNvStorage(VBNV_TRY_RO_SYNC); + } else if (!strcasecmp(name, "battery_cutoff_request")) { + value = VbGetNvStorage(VBNV_BATTERY_CUTOFF_REQUEST); } return value; @@ -687,6 +689,8 @@ int VbSetSystemPropertyInt(const char* name, int value) { return VbSetNvStorage_WithBackup(VBNV_BOOT_ON_AC_DETECT, value); } else if (!strcasecmp(name, "try_ro_sync")) { return VbSetNvStorage_WithBackup(VBNV_TRY_RO_SYNC, value); + } else if (!strcasecmp(name, "battery_cutoff_request")) { + return VbSetNvStorage(VBNV_BATTERY_CUTOFF_REQUEST, value); } return -1; diff --git a/utility/crossystem.c b/utility/crossystem.c index 330a3fd5..c88a444d 100644 --- a/utility/crossystem.c +++ b/utility/crossystem.c @@ -34,6 +34,8 @@ const Param sys_param_list[] = { {"arch", IS_STRING, "Platform architecture"}, {"backup_nvram_request", CAN_WRITE, "Backup the nvram somewhere at the next boot. Cleared on success."}, + {"battery_cutoff_request", CAN_WRITE, + "Cut off battery and shutdown on next boot."}, {"block_devmode", CAN_WRITE, "Block all use of developer mode"}, {"clear_tpm_owner_request", CAN_WRITE, "Clear TPM owner on next boot"}, {"clear_tpm_owner_done", CAN_WRITE, "Clear TPM owner done"}, |