diff options
-rw-r--r-- | src/vendorcode/google/chromeos/Makefile.inc | 5 | ||||
-rw-r--r-- | src/vendorcode/google/chromeos/chromeos.h | 9 | ||||
-rw-r--r-- | src/vendorcode/google/chromeos/vbnv.c | 145 | ||||
-rw-r--r-- | src/vendorcode/google/chromeos/vbnv.h | 41 | ||||
-rw-r--r-- | src/vendorcode/google/chromeos/vbnv_cmos.c | 116 | ||||
-rw-r--r-- | src/vendorcode/google/chromeos/vbnv_ec.c | 86 | ||||
-rw-r--r-- | src/vendorcode/google/chromeos/vbnv_flash.c | 12 |
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]; -} |