aboutsummaryrefslogtreecommitdiff
path: root/src/vendorcode/google/chromeos/vbnv.c
diff options
context:
space:
mode:
authorDuncan Laurie <dlaurie@chromium.org>2016-01-25 17:13:27 -0800
committerPatrick Georgi <pgeorgi@google.com>2016-02-09 13:19:36 +0100
commit88b28ada69d032faf37753f0595658d507859d4a (patch)
tree24ce7c685c3fdf66a434d2f6281ca7e350a530d1 /src/vendorcode/google/chromeos/vbnv.c
parenta7ba56e3ce56c8569e2ac5ddb2d2b6c71458d9cb (diff)
chromeos: Add vbnv wrapper for the different backends
Add a wrapper around the vbnv implementations and call into the different backend functions from there. Also move some of the common functions to the common code and simplify the backend drivers. This will allow some of the code to be re-used so the CMOS backend can backup the data into the flash backend. One side effect of this is that the cache of VBNV was removed from CMOS and EC backends and moved into the VBNV wrapper, but the flash backend also still has a separate cache because it has more state and complexity in the implementation. The wrapper cached data is not used for normal vbnv_read/vbnv_write because some callers need the ability to force a write if the backend storage is cleared (i.e. CMOS clear). BUG=chrome-os-partner:47915 BRANCH=glados TEST=build and boot on chell Change-Id: I4d2e0e99af7e8a44aec77ad9991507401babcca6 Signed-off-by: Patrick Georgi <pgeorgi@chromium.org> Original-Commit-Id: c30f60434a64f6c0eb9ede45d48ddafff19dd24f Original-Change-Id: Ia97f6607c5ad837b9aa10b45211137221ccb93a0 Original-Signed-off-by: Duncan Laurie <dlaurie@chromium.org> Original-Reviewed-on: https://chromium-review.googlesource.com/324120 Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: https://review.coreboot.org/13597 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth <martinroth@google.com>
Diffstat (limited to 'src/vendorcode/google/chromeos/vbnv.c')
-rw-r--r--src/vendorcode/google/chromeos/vbnv.c145
1 files changed, 145 insertions, 0 deletions
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;
+}