aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/vendorcode/google/chromeos/Makefile.inc5
-rw-r--r--src/vendorcode/google/chromeos/chromeos.h9
-rw-r--r--src/vendorcode/google/chromeos/vbnv.c145
-rw-r--r--src/vendorcode/google/chromeos/vbnv.h41
-rw-r--r--src/vendorcode/google/chromeos/vbnv_cmos.c116
-rw-r--r--src/vendorcode/google/chromeos/vbnv_ec.c86
-rw-r--r--src/vendorcode/google/chromeos/vbnv_flash.c12
7 files changed, 201 insertions, 213 deletions
diff --git a/src/vendorcode/google/chromeos/Makefile.inc b/src/vendorcode/google/chromeos/Makefile.inc
index b6d49c2300..ee8b50d9b6 100644
--- a/src/vendorcode/google/chromeos/Makefile.inc
+++ b/src/vendorcode/google/chromeos/Makefile.inc
@@ -18,6 +18,11 @@ verstage-y += chromeos.c
romstage-y += chromeos.c
ramstage-y += chromeos.c
+bootblock-y += vbnv.c
+verstage-y += vbnv.c
+romstage-y += vbnv.c
+ramstage-y += vbnv.c
+
bootblock-$(CONFIG_CHROMEOS_VBNV_CMOS) += vbnv_cmos.c
verstage-$(CONFIG_CHROMEOS_VBNV_CMOS) += vbnv_cmos.c
romstage-$(CONFIG_CHROMEOS_VBNV_CMOS) += vbnv_cmos.c
diff --git a/src/vendorcode/google/chromeos/chromeos.h b/src/vendorcode/google/chromeos/chromeos.h
index 9dbb68129d..03f1516ee0 100644
--- a/src/vendorcode/google/chromeos/chromeos.h
+++ b/src/vendorcode/google/chromeos/chromeos.h
@@ -20,6 +20,7 @@
#include <stdint.h>
#include <bootmode.h>
#include <rules.h>
+#include "vbnv.h"
#include "vboot_common.h"
#include "vboot2/misc.h"
@@ -27,14 +28,6 @@
void save_chromeos_gpios(void);
#endif
-/* functions implemented in vbnv.c: */
-int get_recovery_mode_from_vbnv(void);
-void set_recovery_mode_into_vbnv(int recovery_reason);
-int vboot_wants_oprom(void);
-
-void read_vbnv(uint8_t *vbnv_copy);
-void save_vbnv(const uint8_t *vbnv_copy);
-
#if CONFIG_CHROMEOS
/* functions implemented in elog.c */
void elog_add_boot_reason(void);
diff --git a/src/vendorcode/google/chromeos/vbnv.c b/src/vendorcode/google/chromeos/vbnv.c
new file mode 100644
index 0000000000..92f03fbfe3
--- /dev/null
+++ b/src/vendorcode/google/chromeos/vbnv.c
@@ -0,0 +1,145 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/early_variables.h>
+#include <string.h>
+#include <types.h>
+#include "chromeos.h"
+#include "vbnv.h"
+#include "vbnv_layout.h"
+
+static int vbnv_initialized CAR_GLOBAL;
+static uint8_t vbnv[VBNV_BLOCK_SIZE] CAR_GLOBAL;
+
+/* Wrappers for accessing the variables marked as CAR_GLOBAL. */
+static inline int is_vbnv_initialized(void)
+{
+ return car_get_var(vbnv_initialized);
+}
+
+static inline uint8_t *vbnv_data_addr(int index)
+{
+ uint8_t *vbnv_arr = car_get_var_ptr(vbnv);
+
+ return &vbnv_arr[index];
+}
+
+static inline uint8_t vbnv_data(int index)
+{
+ return *vbnv_data_addr(index);
+}
+
+/* Return CRC-8 of the data, using x^8 + x^2 + x + 1 polynomial. */
+static uint8_t crc8_vbnv(const uint8_t *data, int len)
+{
+ unsigned crc = 0;
+ int i, j;
+
+ for (j = len; j; j--, data++) {
+ crc ^= (*data << 8);
+ for (i = 8; i; i--) {
+ if (crc & 0x8000)
+ crc ^= (0x1070 << 3);
+ crc <<= 1;
+ }
+ }
+
+ return (uint8_t) (crc >> 8);
+}
+
+/* Reset header and CRC to defaults. */
+static void reset_vbnv(uint8_t *vbnv_copy)
+{
+ memset(vbnv_copy, 0, VBNV_BLOCK_SIZE);
+ vbnv_copy[HEADER_OFFSET] = HEADER_SIGNATURE |
+ HEADER_FIRMWARE_SETTINGS_RESET |
+ HEADER_KERNEL_SETTINGS_RESET;
+ vbnv_copy[CRC_OFFSET] = crc8_vbnv(vbnv_copy, CRC_OFFSET);
+}
+
+/* Read VBNV data into cache. */
+static void vbnv_setup(void)
+{
+ if (!is_vbnv_initialized()) {
+ read_vbnv(vbnv_data_addr(0));
+ car_set_var(vbnv_initialized, 1);
+ }
+}
+
+/* Verify VBNV header and checksum. */
+int verify_vbnv(uint8_t *vbnv_copy)
+{
+ return (HEADER_SIGNATURE == (vbnv_copy[HEADER_OFFSET] & HEADER_MASK)) &&
+ (crc8_vbnv(vbnv_copy, CRC_OFFSET) == vbnv_copy[CRC_OFFSET]);
+}
+
+/* Read VBNV data from configured storage backend. */
+void read_vbnv(uint8_t *vbnv_copy)
+{
+ if (IS_ENABLED(CONFIG_CHROMEOS_VBNV_CMOS))
+ read_vbnv_cmos(vbnv_copy);
+ else if (IS_ENABLED(CONFIG_CHROMEOS_VBNV_EC))
+ read_vbnv_ec(vbnv_copy);
+ else if (IS_ENABLED(CONFIG_CHROMEOS_VBNV_FLASH))
+ read_vbnv_flash(vbnv_copy);
+
+ /* Check data for consistency */
+ if (!verify_vbnv(vbnv_copy))
+ reset_vbnv(vbnv_copy);
+}
+
+/*
+ * Write VBNV data to configured storage backend.
+ * This assumes that the caller has updated the CRC already.
+ */
+void save_vbnv(const uint8_t *vbnv_copy)
+{
+ if (IS_ENABLED(CONFIG_CHROMEOS_VBNV_CMOS))
+ save_vbnv_cmos(vbnv_copy);
+ else if (IS_ENABLED(CONFIG_CHROMEOS_VBNV_EC))
+ save_vbnv_ec(vbnv_copy);
+ else if (IS_ENABLED(CONFIG_CHROMEOS_VBNV_FLASH))
+ save_vbnv_flash(vbnv_copy);
+
+ /* Clear initialized flag to force cached data to be updated */
+ car_set_var(vbnv_initialized, 0);
+}
+
+/* Save a recovery reason into VBNV. */
+void set_recovery_mode_into_vbnv(int recovery_reason)
+{
+ uint8_t vbnv_copy[VBNV_BLOCK_SIZE];
+
+ read_vbnv(vbnv_copy);
+
+ vbnv_copy[RECOVERY_OFFSET] = recovery_reason;
+ vbnv_copy[CRC_OFFSET] = crc8_vbnv(vbnv_copy, CRC_OFFSET);
+
+ save_vbnv(vbnv_copy);
+}
+
+/* Read the recovery reason from VBNV. */
+int get_recovery_mode_from_vbnv(void)
+{
+ vbnv_setup();
+ return vbnv_data(RECOVERY_OFFSET);
+}
+
+/* Read the BOOT_OPROM_NEEDED flag from VBNV. */
+int vboot_wants_oprom(void)
+{
+ vbnv_setup();
+ return (vbnv_data(BOOT_OFFSET) & BOOT_OPROM_NEEDED) ? 1 : 0;
+}
diff --git a/src/vendorcode/google/chromeos/vbnv.h b/src/vendorcode/google/chromeos/vbnv.h
new file mode 100644
index 0000000000..3d88507a85
--- /dev/null
+++ b/src/vendorcode/google/chromeos/vbnv.h
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __CHROMEOS_VBNV_H__
+#define __CHROMEOS_VBNV_H__
+
+#include <types.h>
+
+/* Generic functions */
+void read_vbnv(uint8_t *vbnv_copy);
+void save_vbnv(const uint8_t *vbnv_copy);
+int verify_vbnv(uint8_t *vbnv_copy);
+int get_recovery_mode_from_vbnv(void);
+void set_recovery_mode_into_vbnv(int recovery_reason);
+int vboot_wants_oprom(void);
+
+/* CMOS backend */
+void read_vbnv_cmos(uint8_t *vbnv_copy);
+void save_vbnv_cmos(const uint8_t *vbnv_copy);
+
+/* Flash backend */
+void read_vbnv_flash(uint8_t *vbnv_copy);
+void save_vbnv_flash(const uint8_t *vbnv_copy);
+
+/* EC backend */
+void read_vbnv_ec(uint8_t *vbnv_copy);
+void save_vbnv_ec(const uint8_t *vbnv_copy);
+
+#endif
diff --git a/src/vendorcode/google/chromeos/vbnv_cmos.c b/src/vendorcode/google/chromeos/vbnv_cmos.c
index 27f7f0a211..ddcb765fc7 100644
--- a/src/vendorcode/google/chromeos/vbnv_cmos.c
+++ b/src/vendorcode/google/chromeos/vbnv_cmos.c
@@ -14,132 +14,22 @@
*/
#include <types.h>
-#include <string.h>
-#include <cbmem.h>
-#include <console/console.h>
#include <pc80/mc146818rtc.h>
-#include <arch/early_variables.h>
-#include "chromeos.h"
-#if IS_ENABLED(CONFIG_VBOOT_VERIFY_FIRMWARE)
-#include "vboot_handoff.h"
-#endif
+#include "vbnv.h"
#include "vbnv_layout.h"
-static int vbnv_initialized CAR_GLOBAL;
-static uint8_t vbnv[CONFIG_VBNV_SIZE] CAR_GLOBAL;
-
-/* Wrappers for accessing the variables marked as CAR_GLOBAL. */
-static inline int is_vbnv_initialized(void)
-{
- return car_get_var(vbnv_initialized);
-}
-
-static inline uint8_t *vbnv_data_addr(int index)
-{
- uint8_t *vbnv_arr = car_get_var_ptr(vbnv);
-
- return &vbnv_arr[index];
-}
-
-static inline uint8_t vbnv_data(int index)
-{
- return *vbnv_data_addr(index);
-}
-
-/* Return CRC-8 of the data, using x^8 + x^2 + x + 1 polynomial. A
- * table-based algorithm would be faster, but for only 15 bytes isn't
- * worth the code size.
- */
-
-static uint8_t crc8(const uint8_t * data, int len)
-{
- unsigned crc = 0;
- int i, j;
-
- for (j = len; j; j--, data++) {
- crc ^= (*data << 8);
- for (i = 8; i; i--) {
- if (crc & 0x8000)
- crc ^= (0x1070 << 3);
- crc <<= 1;
- }
- }
-
- return (uint8_t) (crc >> 8);
-}
-
-void read_vbnv(uint8_t *vbnv_copy)
+void read_vbnv_cmos(uint8_t *vbnv_copy)
{
int i;
for (i = 0; i < CONFIG_VBNV_SIZE; i++)
vbnv_copy[i] = cmos_read(CONFIG_VBNV_OFFSET + 14 + i);
-
- /* Check data for consistency */
- if ((HEADER_SIGNATURE != (vbnv_copy[HEADER_OFFSET] & HEADER_MASK))
- || (crc8(vbnv_copy, CRC_OFFSET) != vbnv_copy[CRC_OFFSET])) {
-
- /* Data is inconsistent (bad CRC or header),
- * so reset to defaults
- */
- memset(vbnv_copy, 0, VBNV_BLOCK_SIZE);
- vbnv_copy[HEADER_OFFSET] =
- (HEADER_SIGNATURE | HEADER_FIRMWARE_SETTINGS_RESET |
- HEADER_KERNEL_SETTINGS_RESET);
- }
}
-void save_vbnv(const uint8_t *vbnv_copy)
+void save_vbnv_cmos(const uint8_t *vbnv_copy)
{
int i;
for (i = 0; i < CONFIG_VBNV_SIZE; i++)
cmos_write(vbnv_copy[i], CONFIG_VBNV_OFFSET + 14 + i);
}
-
-
-static void vbnv_setup(void)
-{
- read_vbnv(vbnv_data_addr(0));
- car_set_var(vbnv_initialized, 1);
-}
-
-void set_recovery_mode_into_vbnv(int recovery_reason)
-{
- uint8_t vbnv_copy[CONFIG_VBNV_SIZE];
- uint8_t crc_val;
-
- read_vbnv(vbnv_copy);
-
- vbnv_copy[RECOVERY_OFFSET] = recovery_reason;
-
- crc_val = crc8(vbnv_copy, CRC_OFFSET);
-
- vbnv_copy[CRC_OFFSET] = crc_val;
-
- save_vbnv(vbnv_copy);
-}
-
-int get_recovery_mode_from_vbnv(void)
-{
- if (!is_vbnv_initialized())
- vbnv_setup();
- return vbnv_data(RECOVERY_OFFSET);
-}
-
-int vboot_wants_oprom(void)
-{
-#if IS_ENABLED(CONFIG_VBOOT_VERIFY_FIRMWARE)
- struct vboot_handoff *vbho;
-
- /* First check if handoff structure flag exists and is set. */
- vbho = cbmem_find(CBMEM_ID_VBOOT_HANDOFF);
- if (vbho && vbho->init_params.flags & VB_INIT_FLAG_OPROM_LOADED)
- return 1;
-#endif
-
- if (!is_vbnv_initialized())
- vbnv_setup();
-
- return (vbnv_data(BOOT_OFFSET) & BOOT_OPROM_NEEDED) ? 1 : 0;
-}
diff --git a/src/vendorcode/google/chromeos/vbnv_ec.c b/src/vendorcode/google/chromeos/vbnv_ec.c
index 6e1b0c5f70..0b7b7b5b68 100644
--- a/src/vendorcode/google/chromeos/vbnv_ec.c
+++ b/src/vendorcode/google/chromeos/vbnv_ec.c
@@ -14,96 +14,16 @@
*/
#include <types.h>
-#include <string.h>
-#include <console/console.h>
-#include <arch/early_variables.h>
#include <ec/google/chromeec/ec.h>
-#include "chromeos.h"
+#include "vbnv.h"
#include "vbnv_layout.h"
-static int vbnv_initialized CAR_GLOBAL;
-static uint8_t vbnv[VBNV_BLOCK_SIZE] CAR_GLOBAL;
-
-/* Wrappers for accessing the variables marked as CAR_GLOBAL. */
-static inline int is_vbnv_initialized(void)
-{
- return car_get_var(vbnv_initialized);
-}
-
-static inline uint8_t *vbnv_data_addr(int index)
-{
- uint8_t *vbnv_arr = car_get_var_ptr(vbnv);
-
- return &vbnv_arr[index];
-}
-
-static inline uint8_t vbnv_data(int index)
-{
- return *vbnv_data_addr(index);
-}
-
-/* Return CRC-8 of the data, using x^8 + x^2 + x + 1 polynomial. A
- * table-based algorithm would be faster, but for only 15 bytes isn't
- * worth the code size.
- */
-
-static uint8_t crc8(const uint8_t * data, int len)
-{
- unsigned crc = 0;
- int i, j;
-
- for (j = len; j; j--, data++) {
- crc ^= (*data << 8);
- for (i = 8; i; i--) {
- if (crc & 0x8000)
- crc ^= (0x1070 << 3);
- crc <<= 1;
- }
- }
-
- return (uint8_t) (crc >> 8);
-}
-
-void read_vbnv(uint8_t *vbnv_copy)
+void read_vbnv_ec(uint8_t *vbnv_copy)
{
google_chromeec_vbnv_context(1, vbnv_copy, VBNV_BLOCK_SIZE);
-
- /* Check data for consistency */
- if ((HEADER_SIGNATURE != (vbnv_copy[HEADER_OFFSET] & HEADER_MASK))
- || (crc8(vbnv_copy, CRC_OFFSET) != vbnv_copy[CRC_OFFSET])) {
-
- /* Data is inconsistent (bad CRC or header),
- * so reset to defaults
- */
- memset(vbnv_copy, 0, VBNV_BLOCK_SIZE);
- vbnv_copy[HEADER_OFFSET] =
- (HEADER_SIGNATURE | HEADER_FIRMWARE_SETTINGS_RESET |
- HEADER_KERNEL_SETTINGS_RESET);
- }
}
-void save_vbnv(const uint8_t *vbnv_copy)
+void save_vbnv_ec(const uint8_t *vbnv_copy)
{
google_chromeec_vbnv_context(0, (uint8_t *)vbnv_copy, VBNV_BLOCK_SIZE);
}
-
-static void vbnv_setup(void)
-{
- read_vbnv(vbnv_data_addr(0));
- car_set_var(vbnv_initialized, 1);
-}
-
-int get_recovery_mode_from_vbnv(void)
-{
- if (!is_vbnv_initialized())
- vbnv_setup();
- return vbnv_data(RECOVERY_OFFSET);
-}
-
-int vboot_wants_oprom(void)
-{
- if (!is_vbnv_initialized())
- vbnv_setup();
-
- return (vbnv_data(BOOT_OFFSET) & BOOT_OPROM_NEEDED) ? 1 : 0;
-}
diff --git a/src/vendorcode/google/chromeos/vbnv_flash.c b/src/vendorcode/google/chromeos/vbnv_flash.c
index f8a88cd33e..ea5d9f3ff9 100644
--- a/src/vendorcode/google/chromeos/vbnv_flash.c
+++ b/src/vendorcode/google/chromeos/vbnv_flash.c
@@ -22,6 +22,7 @@
#include <vb2_api.h>
#include <vboot_nvstorage.h>
#include "chromeos.h"
+#include "vbnv.h"
#include "vbnv_layout.h"
#define BLOB_SIZE VB2_NVDATA_SIZE
@@ -157,7 +158,7 @@ static int erase_nvram(void)
return 0;
}
-void read_vbnv(uint8_t *vbnv_copy)
+void read_vbnv_flash(uint8_t *vbnv_copy)
{
if (!is_initialized())
if (init_vbnv())
@@ -165,7 +166,7 @@ void read_vbnv(uint8_t *vbnv_copy)
memcpy(vbnv_copy, cache, BLOB_SIZE);
}
-void save_vbnv(const uint8_t *vbnv_copy)
+void save_vbnv_flash(const uint8_t *vbnv_copy)
{
int new_offset;
int i;
@@ -205,10 +206,3 @@ void save_vbnv(const uint8_t *vbnv_copy)
printk(BIOS_ERR, "failed to save nvdata\n");
}
}
-
-int get_recovery_mode_from_vbnv(void)
-{
- if (!is_initialized())
- init_vbnv();
- return cache[RECOVERY_OFFSET];
-}