blob: a5a780664c3a97223efa3496555ae9d0e8c1f74c [file] [log] [blame]
Duncan Laurie88b28ad2016-01-25 17:13:27 -08001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2016 Google Inc.
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.
14 */
15
Duncan Laurie88b28ad2016-01-25 17:13:27 -080016#include <string.h>
17#include <types.h>
Philipp Deppenwiesefea24292017-10-17 17:02:29 +020018#include <security/vboot/vbnv.h>
19#include <security/vboot/vbnv_layout.h>
Duncan Laurie88b28ad2016-01-25 17:13:27 -080020
Arthur Heymans344e86b2019-11-20 19:47:10 +010021static int vbnv_initialized;
22static uint8_t vbnv[VBOOT_VBNV_BLOCK_SIZE];
Duncan Laurie88b28ad2016-01-25 17:13:27 -080023
24/* Return CRC-8 of the data, using x^8 + x^2 + x + 1 polynomial. */
25static uint8_t crc8_vbnv(const uint8_t *data, int len)
26{
Martin Roth468d02c2019-10-23 21:44:42 -060027 unsigned int crc = 0;
Duncan Laurie88b28ad2016-01-25 17:13:27 -080028 int i, j;
29
30 for (j = len; j; j--, data++) {
31 crc ^= (*data << 8);
32 for (i = 8; i; i--) {
33 if (crc & 0x8000)
34 crc ^= (0x1070 << 3);
35 crc <<= 1;
36 }
37 }
38
39 return (uint8_t) (crc >> 8);
40}
41
Aaron Durbinfe265a12017-09-15 11:17:38 -060042void vbnv_reset(uint8_t *vbnv_copy)
Duncan Laurie88b28ad2016-01-25 17:13:27 -080043{
Furquan Shaikh2a12e2e2016-07-25 11:48:03 -070044 memset(vbnv_copy, 0, VBOOT_VBNV_BLOCK_SIZE);
Duncan Laurie88b28ad2016-01-25 17:13:27 -080045}
46
47/* Read VBNV data into cache. */
48static void vbnv_setup(void)
49{
Arthur Heymans344e86b2019-11-20 19:47:10 +010050 if (!vbnv_initialized) {
51 read_vbnv(vbnv);
52 vbnv_initialized = 1;
Duncan Laurie88b28ad2016-01-25 17:13:27 -080053 }
54}
55
56/* Verify VBNV header and checksum. */
57int verify_vbnv(uint8_t *vbnv_copy)
58{
59 return (HEADER_SIGNATURE == (vbnv_copy[HEADER_OFFSET] & HEADER_MASK)) &&
60 (crc8_vbnv(vbnv_copy, CRC_OFFSET) == vbnv_copy[CRC_OFFSET]);
61}
62
Hung-Te Linfe2fc832016-12-29 20:59:37 +080063/* Re-generate VBNV checksum. */
64void regen_vbnv_crc(uint8_t *vbnv_copy)
65{
66 vbnv_copy[CRC_OFFSET] = crc8_vbnv(vbnv_copy, CRC_OFFSET);
67}
68
Furquan Shaikh165b6cf2016-06-27 16:19:09 -070069/*
70 * Read VBNV data from configured storage backend.
71 * If VBNV verification fails, reset the vbnv copy.
Furquan Shaikh165b6cf2016-06-27 16:19:09 -070072 */
Furquan Shaikhbe87f732016-06-29 11:26:27 -070073void read_vbnv(uint8_t *vbnv_copy)
Duncan Laurie88b28ad2016-01-25 17:13:27 -080074{
Julius Wernercd49cce2019-03-05 16:53:33 -080075 if (CONFIG(VBOOT_VBNV_CMOS))
Duncan Laurie88b28ad2016-01-25 17:13:27 -080076 read_vbnv_cmos(vbnv_copy);
Julius Wernercd49cce2019-03-05 16:53:33 -080077 else if (CONFIG(VBOOT_VBNV_EC))
Duncan Laurie88b28ad2016-01-25 17:13:27 -080078 read_vbnv_ec(vbnv_copy);
Julius Wernercd49cce2019-03-05 16:53:33 -080079 else if (CONFIG(VBOOT_VBNV_FLASH))
Duncan Laurie88b28ad2016-01-25 17:13:27 -080080 read_vbnv_flash(vbnv_copy);
81
82 /* Check data for consistency */
Furquan Shaikhbe87f732016-06-29 11:26:27 -070083 if (!verify_vbnv(vbnv_copy))
Aaron Durbinfe265a12017-09-15 11:17:38 -060084 vbnv_reset(vbnv_copy);
Duncan Laurie88b28ad2016-01-25 17:13:27 -080085}
86
87/*
88 * Write VBNV data to configured storage backend.
89 * This assumes that the caller has updated the CRC already.
90 */
91void save_vbnv(const uint8_t *vbnv_copy)
92{
Julius Wernercd49cce2019-03-05 16:53:33 -080093 if (CONFIG(VBOOT_VBNV_CMOS))
Duncan Laurie88b28ad2016-01-25 17:13:27 -080094 save_vbnv_cmos(vbnv_copy);
Julius Wernercd49cce2019-03-05 16:53:33 -080095 else if (CONFIG(VBOOT_VBNV_EC))
Duncan Laurie88b28ad2016-01-25 17:13:27 -080096 save_vbnv_ec(vbnv_copy);
Julius Wernercd49cce2019-03-05 16:53:33 -080097 else if (CONFIG(VBOOT_VBNV_FLASH))
Duncan Laurie88b28ad2016-01-25 17:13:27 -080098 save_vbnv_flash(vbnv_copy);
99
100 /* Clear initialized flag to force cached data to be updated */
Arthur Heymans344e86b2019-11-20 19:47:10 +0100101 vbnv_initialized = 0;
Duncan Laurie88b28ad2016-01-25 17:13:27 -0800102}
103
Furquan Shaikh37c721d2018-04-25 18:13:03 -0700104/* Read the USB Device Controller(UDC) enable flag from VBNV. */
105int vbnv_udc_enable_flag(void)
106{
107 vbnv_setup();
Arthur Heymans344e86b2019-11-20 19:47:10 +0100108 return (vbnv[DEV_FLAGS_OFFSET] & DEV_ENABLE_UDC) ? 1 : 0;
Furquan Shaikh37c721d2018-04-25 18:13:03 -0700109}
110
Aaron Durbin118a84f2017-09-15 11:15:07 -0600111void vbnv_init(uint8_t *vbnv_copy)
112{
Julius Wernercd49cce2019-03-05 16:53:33 -0800113 if (CONFIG(VBOOT_VBNV_CMOS))
Aaron Durbin0990fbf2017-09-15 15:23:04 -0600114 vbnv_init_cmos(vbnv_copy);
Aaron Durbin118a84f2017-09-15 11:15:07 -0600115 read_vbnv(vbnv_copy);
116}