blob: 6e1b0c5f70a65b71050ea84d192c69ea674d66ad [file] [log] [blame]
Stefan Reinauer9aea04a2012-03-30 12:01:06 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Stefan Reinauer9aea04a2012-03-30 12:01:06 -070014 */
15
16#include <types.h>
17#include <string.h>
18#include <console/console.h>
Stefan Reinauerfd4f4132013-06-19 12:25:44 -070019#include <arch/early_variables.h>
Stefan Reinaueraaaf6892013-08-29 15:57:11 -070020#include <ec/google/chromeec/ec.h>
Stefan Reinauer9aea04a2012-03-30 12:01:06 -070021#include "chromeos.h"
David Hendricks6fd35012015-01-02 15:16:41 -080022#include "vbnv_layout.h"
Stefan Reinauer9aea04a2012-03-30 12:01:06 -070023
24static int vbnv_initialized CAR_GLOBAL;
Stefan Reinaueraaaf6892013-08-29 15:57:11 -070025static uint8_t vbnv[VBNV_BLOCK_SIZE] CAR_GLOBAL;
Aaron Durbin677e1552013-05-10 00:42:14 -050026
27/* Wrappers for accessing the variables marked as CAR_GLOBAL. */
28static inline int is_vbnv_initialized(void)
29{
30 return car_get_var(vbnv_initialized);
31}
32
33static inline uint8_t *vbnv_data_addr(int index)
34{
35 uint8_t *vbnv_arr = car_get_var_ptr(vbnv);
36
37 return &vbnv_arr[index];
38}
39
40static inline uint8_t vbnv_data(int index)
41{
42 return *vbnv_data_addr(index);
43}
Stefan Reinauer9aea04a2012-03-30 12:01:06 -070044
45/* Return CRC-8 of the data, using x^8 + x^2 + x + 1 polynomial. A
46 * table-based algorithm would be faster, but for only 15 bytes isn't
47 * worth the code size.
48 */
49
50static uint8_t crc8(const uint8_t * data, int len)
51{
52 unsigned crc = 0;
53 int i, j;
54
55 for (j = len; j; j--, data++) {
56 crc ^= (*data << 8);
57 for (i = 8; i; i--) {
58 if (crc & 0x8000)
59 crc ^= (0x1070 << 3);
60 crc <<= 1;
61 }
62 }
63
64 return (uint8_t) (crc >> 8);
65}
66
Aaron Durbinfd795622013-03-01 17:12:26 -060067void read_vbnv(uint8_t *vbnv_copy)
Stefan Reinauer9aea04a2012-03-30 12:01:06 -070068{
Stefan Reinaueraaaf6892013-08-29 15:57:11 -070069 google_chromeec_vbnv_context(1, vbnv_copy, VBNV_BLOCK_SIZE);
Stefan Reinauer9aea04a2012-03-30 12:01:06 -070070
71 /* Check data for consistency */
Aaron Durbinfd795622013-03-01 17:12:26 -060072 if ((HEADER_SIGNATURE != (vbnv_copy[HEADER_OFFSET] & HEADER_MASK))
73 || (crc8(vbnv_copy, CRC_OFFSET) != vbnv_copy[CRC_OFFSET])) {
Stefan Reinauer9aea04a2012-03-30 12:01:06 -070074
75 /* Data is inconsistent (bad CRC or header),
76 * so reset to defaults
77 */
Aaron Durbinfd795622013-03-01 17:12:26 -060078 memset(vbnv_copy, 0, VBNV_BLOCK_SIZE);
79 vbnv_copy[HEADER_OFFSET] =
Stefan Reinauer9aea04a2012-03-30 12:01:06 -070080 (HEADER_SIGNATURE | HEADER_FIRMWARE_SETTINGS_RESET |
81 HEADER_KERNEL_SETTINGS_RESET);
82 }
Aaron Durbinfd795622013-03-01 17:12:26 -060083}
84
85void save_vbnv(const uint8_t *vbnv_copy)
86{
Stefan Reinaueraaaf6892013-08-29 15:57:11 -070087 google_chromeec_vbnv_context(0, (uint8_t *)vbnv_copy, VBNV_BLOCK_SIZE);
Aaron Durbinfd795622013-03-01 17:12:26 -060088}
89
Aaron Durbinfd795622013-03-01 17:12:26 -060090static void vbnv_setup(void)
91{
Aaron Durbin677e1552013-05-10 00:42:14 -050092 read_vbnv(vbnv_data_addr(0));
93 car_set_var(vbnv_initialized, 1);
Stefan Reinauer9aea04a2012-03-30 12:01:06 -070094}
95
96int get_recovery_mode_from_vbnv(void)
97{
Aaron Durbin677e1552013-05-10 00:42:14 -050098 if (!is_vbnv_initialized())
Stefan Reinauer9aea04a2012-03-30 12:01:06 -070099 vbnv_setup();
Aaron Durbin677e1552013-05-10 00:42:14 -0500100 return vbnv_data(RECOVERY_OFFSET);
Stefan Reinauer9aea04a2012-03-30 12:01:06 -0700101}
Bill Richardson0a405ba2012-06-26 16:33:45 -0700102
103int vboot_wants_oprom(void)
104{
Aaron Durbin677e1552013-05-10 00:42:14 -0500105 if (!is_vbnv_initialized())
Bill Richardson0a405ba2012-06-26 16:33:45 -0700106 vbnv_setup();
107
Bill Richardson6a89cf32012-07-10 17:54:59 -0700108 return (vbnv_data(BOOT_OFFSET) & BOOT_OPROM_NEEDED) ? 1 : 0;
Bill Richardson0a405ba2012-06-26 16:33:45 -0700109}