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.

Change-Id: If4156b5e14c6923c5b331c7e5feaabbffe1dad37
Reviewed-on: https://gerrit.chromium.org/gerrit/29199
Commit-Ready: Randall Spangler <rspangler@chromium.org>
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Tested-by: Randall Spangler <rspangler@chromium.org>
This commit is contained in:
Randall Spangler
2012-08-03 12:48:24 -07:00
committed by Gerrit
parent 63a0c47f50
commit da8d32dc8d
5 changed files with 90 additions and 63 deletions

View File

@@ -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

View File

@@ -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;

View File

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

View File

@@ -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.
*

View File

@@ -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")) {