From 8997979183316951793c24c802abea10ce9fcb91 Mon Sep 17 00:00:00 2001 From: Randall Spangler Date: Fri, 3 Aug 2012 12:48:24 -0700 Subject: Crossystem should return at-boot switch positions from VbSharedData This is more reliable than reading them through FDT/ACPI, since it reflects the positions as shown to verified boot code. Notes: 1. This affects ALL platforms with virtual dev switches (x86 AND arm) 2. The fix should have no effect on older platforms, but I haven't tested those. BUG=chrome-os-partner:11805 TEST=manual 1. boot in normal mode. devsw_boot = 0 # Developer switch position at boot recovery_reason = 0 # Recovery mode reason for current boot recoverysw_boot = 0 # Recovery switch position at boot wpsw_boot = 1 # Firmware write protect hardware switch position at boot 2. boot in developer mode. localhost ~ # crossystem devsw_boot = 1 # Developer switch position at boot recovery_reason = 0 # Recovery mode reason for current boot recoverysw_boot = 0 # Recovery switch position at boot wpsw_boot = 1 # Firmware write protect hardware switch position at boot 3. boot in developer-recovery mode using keyboard combo. devsw_boot = 1 # Developer switch position at boot recovery_reason = 2 # Recovery mode reason for current boot recoverysw_boot = 1 # Recovery switch position at boot wpsw_boot = 1 # Firmware write protect hardware switch position at boot 4. disable WP and reboot. wpsw_boot should be 0. Original-Change-Id: If4156b5e14c6923c5b331c7e5feaabbffe1dad37 (cherry picked from commit da8d32dc8d0fb5ebcfffa305f4a3ecb2dd7c79ac) Change-Id: I6b80c4f507ebbb9accb75ad6b21b0b5bd963921a Signed-off-by: Randall Spangler Reviewed-on: https://gerrit.chromium.org/gerrit/29320 --- firmware/include/vboot_struct.h | 8 ++++- host/arch/arm/lib/crossystem_arch.c | 25 ++-------------- host/arch/x86/lib/crossystem_arch.c | 54 ++++++++++++++++----------------- host/include/crossystem_arch.h | 6 ++-- host/lib/crossystem.c | 60 +++++++++++++++++++++++++++++++------ 5 files changed, 90 insertions(+), 63 deletions(-) diff --git a/firmware/include/vboot_struct.h b/firmware/include/vboot_struct.h index 7000f6e8..4b951b2a 100644 --- a/firmware/include/vboot_struct.h +++ b/firmware/include/vboot_struct.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved. +/* Copyright (c) 2012 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. * @@ -236,6 +236,12 @@ typedef struct VbKernelPreambleHeader { /* VbInit() was told the system supports EC software sync */ #define VBSD_EC_SOFTWARE_SYNC 0x00000800 +/* Supported flags by header version. It's ok to add new flags while keeping + * struct version 2 as long as flag-NOT-present is the correct value for + * existing hardware (Stumpy/Lumpy). */ +#define VBSD_FLAGS_VERSION_1 0x00000007 /* Alex, ZGB */ +#define VBSD_FLAGS_VERSION_2 0x00000F7F + /* Result codes for VbSharedDataHeader.check_fw_a_result (and b_result) */ #define VBSD_LF_CHECK_NOT_DONE 0 #define VBSD_LF_CHECK_DEV_MISMATCH 1 diff --git a/host/arch/arm/lib/crossystem_arch.c b/host/arch/arm/lib/crossystem_arch.c index 76be1588..3ccb0baf 100644 --- a/host/arch/arm/lib/crossystem_arch.c +++ b/host/arch/arm/lib/crossystem_arch.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved. +/* Copyright (c) 2012 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. */ @@ -89,20 +89,6 @@ static int ReadFdtValue(const char *property, int *value) { return 0; } -static int ReadFdtBool(const char *property) { - char filename[FNAME_SIZE]; - struct stat tmp; - int err; - - snprintf(filename, sizeof(filename), FDT_BASE_PATH "/%s", property); - err = stat(filename, &tmp); - - if (err == 0) - return 1; - - return 0; -} - static int ReadFdtInt(const char *property) { int value; if (ReadFdtValue(property, &value)) @@ -368,19 +354,14 @@ VbSharedDataHeader *VbSharedDataRead(void) { int VbGetArchPropertyInt(const char* name) { if (!strcasecmp(name, "fmap_base")) return ReadFdtInt("fmap-offset"); - else if (!strcasecmp(name, "devsw_boot")) - return ReadFdtBool("boot-developer-switch"); - else if (!strcasecmp(name, "recoverysw_boot")) - return ReadFdtBool("boot-recovery-switch"); - else if (!strcasecmp(name, "wpsw_boot")) - return ReadFdtBool("boot-write-protect-switch"); else if (!strcasecmp(name, "devsw_cur")) return VbGetVarGpio("developer-switch"); else if (!strcasecmp(name, "recoverysw_cur")) return VbGetVarGpio("recovery-switch"); else if (!strcasecmp(name, "wpsw_cur")) - return VbGetVarGpio("write-protect-switch"); + return VbGetVarGpio("write-protect-switch"); else if (!strcasecmp(name, "recoverysw_ec_boot")) + /* TODO: read correct value using ectool */ return 0; else return -1; diff --git a/host/arch/x86/lib/crossystem_arch.c b/host/arch/x86/lib/crossystem_arch.c index b0ab10fa..448a8ffa 100644 --- a/host/arch/x86/lib/crossystem_arch.c +++ b/host/arch/x86/lib/crossystem_arch.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved. +/* Copyright (c) 2012 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. */ @@ -426,19 +426,8 @@ static const char* VbReadMainFwType(char* dest, int size) { /* Read the recovery reason. Returns the reason code or -1 if error. */ static int VbGetRecoveryReason(void) { - VbSharedDataHeader* sh; int value = -1; - /* Try reading from VbSharedData first */ - sh = VbSharedDataRead(); - if (sh) { - if (sh->struct_version >= 2) - value = sh->recovery_reason; - free(sh); - if (-1 != value) - return value; - } - /* Try reading type from BINF.4 */ value = ReadFileInt(ACPI_BINF_PATH ".4"); if (-1 != value) @@ -601,13 +590,11 @@ int VbGetArchPropertyInt(const char* name) { int value = -1; /* Values from ACPI */ - if (!strcasecmp(name,"recovery_reason")) { - value = VbGetRecoveryReason(); - } else if (!strcasecmp(name,"fmap_base")) { + if (!strcasecmp(name,"fmap_base")) value = ReadFileInt(ACPI_FMAP_PATH); - } + /* Switch positions */ - else if (!strcasecmp(name,"devsw_cur")) { + if (!strcasecmp(name,"devsw_cur")) { value = ReadGpio(GPIO_SIGNAL_TYPE_DEV); } else if (!strcasecmp(name,"recoverysw_cur")) { value = ReadGpio(GPIO_SIGNAL_TYPE_RECOVERY); @@ -615,28 +602,36 @@ int VbGetArchPropertyInt(const char* name) { value = ReadGpio(GPIO_SIGNAL_TYPE_WP); if (-1 != value && FwidStartsWith("Mario.")) value = 1 - value; /* Mario reports this backwards */ - } else if (!strcasecmp(name,"devsw_boot")) { - value = ReadFileBit(ACPI_CHSW_PATH, CHSW_DEV_BOOT); - } else if (!strcasecmp(name,"recoverysw_boot")) { - value = ReadFileBit(ACPI_CHSW_PATH, CHSW_RECOVERY_BOOT); } else if (!strcasecmp(name,"recoverysw_ec_boot")) { value = ReadFileBit(ACPI_CHSW_PATH, CHSW_RECOVERY_EC_BOOT); - } else if (!strcasecmp(name,"wpsw_boot")) { - value = ReadFileBit(ACPI_CHSW_PATH, CHSW_WP_BOOT); - if (-1 != value && FwidStartsWith("Mario.")) - value = 1 - value; /* Mario reports this backwards */ + } + + /* Fields for old systems which don't have VbSharedData */ + if (VbSharedDataVersion() < 2) { + if (!strcasecmp(name,"recovery_reason")) { + value = VbGetRecoveryReason(); + } else if (!strcasecmp(name,"devsw_boot")) { + value = ReadFileBit(ACPI_CHSW_PATH, CHSW_DEV_BOOT); + } else if (!strcasecmp(name,"recoverysw_boot")) { + value = ReadFileBit(ACPI_CHSW_PATH, CHSW_RECOVERY_BOOT); + } else if (!strcasecmp(name,"wpsw_boot")) { + value = ReadFileBit(ACPI_CHSW_PATH, CHSW_WP_BOOT); + if (-1 != value && FwidStartsWith("Mario.")) + value = 1 - value; /* Mario reports this backwards */ + } } /* Saved memory is at a fixed location for all H2C BIOS. If the CHSW * path exists in sysfs, it's a H2C BIOS. */ - else if (!strcasecmp(name,"savedmem_base")) { + if (!strcasecmp(name,"savedmem_base")) { return (-1 == ReadFileInt(ACPI_CHSW_PATH) ? -1 : 0x00F00000); } else if (!strcasecmp(name,"savedmem_size")) { return (-1 == ReadFileInt(ACPI_CHSW_PATH) ? -1 : 0x00100000); } + /* NV storage values. If unable to get from NV storage, fall back to the - * CMOS reboot field used by older BIOS. */ - else if (!strcasecmp(name,"recovery_request")) { + * CMOS reboot field used by older BIOS (e.g. Mario). */ + if (!strcasecmp(name,"recovery_request")) { value = VbGetNvStorage(VBNV_RECOVERY_REQUEST); if (-1 == value) value = VbGetCmosRebootField(CMOSRF_RECOVERY); @@ -649,10 +644,11 @@ int VbGetArchPropertyInt(const char* name) { if (-1 == value) value = VbGetCmosRebootField(CMOSRF_TRY_B); } + /* Firmware update tries is now stored in the kernel field. On * older systems where it's not, it was stored in a file in the * stateful partition. */ - else if (!strcasecmp(name,"fwupdate_tries")) { + if (!strcasecmp(name,"fwupdate_tries")) { if (-1 != VbGetNvStorage(VBNV_KERNEL_FIELD)) return -1; /* NvStorage supported; fail through arch-specific * implementation to normal implementation. */ diff --git a/host/include/crossystem_arch.h b/host/include/crossystem_arch.h index be6b5439..4044c749 100644 --- a/host/include/crossystem_arch.h +++ b/host/include/crossystem_arch.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved. +/* Copyright (c) 2012 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. * @@ -36,8 +36,10 @@ int VbSetNvStorage(VbNvParam param, int value); /* Return true if the FWID starts with the specified string. */ int FwidStartsWith(const char *start); +/* Return version of VbSharedData struct or -1 if not found. */ +int VbSharedDataVersion(void); -/* APIS WITH ARCH-SPECIFIC IMPLEMENTATIONS */ +/* Apis WITH ARCH-SPECIFIC IMPLEMENTATIONS */ /* Read the non-volatile context from NVRAM. * diff --git a/host/lib/crossystem.c b/host/lib/crossystem.c index 1515ecf3..e120abcc 100644 --- a/host/lib/crossystem.c +++ b/host/lib/crossystem.c @@ -34,6 +34,12 @@ typedef enum VdatStringField { /* Fields that GetVdatInt() can get */ typedef enum VdatIntField { VDAT_INT_FLAGS = 0, /* Flags */ + VDAT_INT_HEADER_VERSION, /* Header version for VbSharedData */ + VDAT_INT_DEVSW_BOOT, /* Dev switch position at boot */ + VDAT_INT_DEVSW_VIRTUAL, /* Dev switch is virtual */ + VDAT_INT_RECSW_BOOT, /* Recovery switch position at boot */ + VDAT_INT_WPSW_BOOT, /* WP switch position at boot */ + VDAT_INT_FW_VERSION_TPM, /* Current firmware version in TPM */ VDAT_INT_KERNEL_VERSION_TPM, /* Current kernel version in TPM */ VDAT_INT_TRIED_FIRMWARE_B, /* Tried firmware B due to fwb_tries */ @@ -322,15 +328,13 @@ int GetVdatInt(VdatIntField field) { if (!sh) return -1; + /* Fields supported in version 1 */ switch (field) { case VDAT_INT_FLAGS: value = (int)sh->flags; break; - case VDAT_INT_FW_VERSION_TPM: - value = (int)sh->fw_version_tpm; - break; - case VDAT_INT_KERNEL_VERSION_TPM: - value = (int)sh->kernel_version_tpm; + case VDAT_INT_HEADER_VERSION: + value = sh->struct_version; break; case VDAT_INT_TRIED_FIRMWARE_B: value = (sh->flags & VBSD_FWB_TRIED ? 1 : 0); @@ -338,17 +342,47 @@ int GetVdatInt(VdatIntField field) { case VDAT_INT_KERNEL_KEY_VERIFIED: value = (sh->flags & VBSD_KERNEL_KEY_VERIFIED ? 1 : 0); break; - case VDAT_INT_RECOVERY_REASON: - /* Field added in struct version 2 */ - if (sh->struct_version >= 2) - value = sh->recovery_reason; + default: break; } + /* Fields added in struct version 2 */ + if (sh->struct_version >= 2) { + switch(field) { + case VDAT_INT_DEVSW_BOOT: + value = (sh->flags & VBSD_BOOT_DEV_SWITCH_ON ? 1 : 0); + break; + case VDAT_INT_DEVSW_VIRTUAL: + value = (sh->flags & VBSD_HONOR_VIRT_DEV_SWITCH ? 1 : 0); + break; + case VDAT_INT_RECSW_BOOT: + value = (sh->flags & VBSD_BOOT_REC_SWITCH_ON ? 1 : 0); + break; + case VDAT_INT_WPSW_BOOT: + value = (sh->flags & VBSD_BOOT_FIRMWARE_WP_ENABLED ? 1 : 0); + break; + case VDAT_INT_FW_VERSION_TPM: + value = (int)sh->fw_version_tpm; + break; + case VDAT_INT_KERNEL_VERSION_TPM: + value = (int)sh->kernel_version_tpm; + break; + case VDAT_INT_RECOVERY_REASON: + value = sh->recovery_reason; + break; + default: + break; + } + } + free(sh); return value; } +/* Return version of VbSharedData struct or -1 if not found. */ +int VbSharedDataVersion(void) { + return GetVdatInt(VDAT_INT_HEADER_VERSION); +} int VbGetSystemPropertyInt(const char* name) { int value = -1; @@ -387,6 +421,14 @@ int VbGetSystemPropertyInt(const char* name) { /* Other parameters */ else if (!strcasecmp(name,"cros_debug")) { value = VbGetCrosDebug(); + } else if (!strcasecmp(name,"devsw_boot")) { + value = GetVdatInt(VDAT_INT_DEVSW_BOOT); + } else if (!strcasecmp(name,"devsw_virtual")) { + value = GetVdatInt(VDAT_INT_DEVSW_VIRTUAL); + } else if (!strcasecmp(name, "recoverysw_boot")) { + value = GetVdatInt(VDAT_INT_RECSW_BOOT); + } else if (!strcasecmp(name, "wpsw_boot")) { + value = GetVdatInt(VDAT_INT_WPSW_BOOT); } else if (!strcasecmp(name,"vdat_flags")) { value = GetVdatInt(VDAT_INT_FLAGS); } else if (!strcasecmp(name,"tpm_fwver")) { -- cgit v1.2.1