blob: e9223c08aee9a2031c8a1d8f548b3d7babdbdf8c [file] [log] [blame]
Angel Pons986d50e2020-04-02 23:48:53 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Duncan Laurie88b28ad2016-01-25 17:13:27 -08002
Yu-Ping Wu6b0d0852022-06-08 10:23:32 +08003#include <assert.h>
Duncan Laurie88b28ad2016-01-25 17:13:27 -08004#include <string.h>
5#include <types.h>
Philipp Deppenwiesefea24292017-10-17 17:02:29 +02006#include <security/vboot/vbnv.h>
7#include <security/vboot/vbnv_layout.h>
Duncan Laurie88b28ad2016-01-25 17:13:27 -08008
Arthur Heymans344e86b2019-11-20 19:47:10 +01009static int vbnv_initialized;
10static uint8_t vbnv[VBOOT_VBNV_BLOCK_SIZE];
Duncan Laurie88b28ad2016-01-25 17:13:27 -080011
12/* Return CRC-8 of the data, using x^8 + x^2 + x + 1 polynomial. */
13static uint8_t crc8_vbnv(const uint8_t *data, int len)
14{
Martin Roth468d02c2019-10-23 21:44:42 -060015 unsigned int crc = 0;
Duncan Laurie88b28ad2016-01-25 17:13:27 -080016 int i, j;
17
18 for (j = len; j; j--, data++) {
19 crc ^= (*data << 8);
20 for (i = 8; i; i--) {
21 if (crc & 0x8000)
22 crc ^= (0x1070 << 3);
23 crc <<= 1;
24 }
25 }
26
Elyes Haouasb538d712022-11-18 15:03:07 +010027 return (uint8_t)(crc >> 8);
Duncan Laurie88b28ad2016-01-25 17:13:27 -080028}
29
Aaron Durbinfe265a12017-09-15 11:17:38 -060030void vbnv_reset(uint8_t *vbnv_copy)
Duncan Laurie88b28ad2016-01-25 17:13:27 -080031{
Furquan Shaikh2a12e2e2016-07-25 11:48:03 -070032 memset(vbnv_copy, 0, VBOOT_VBNV_BLOCK_SIZE);
Duncan Laurie88b28ad2016-01-25 17:13:27 -080033}
34
35/* Read VBNV data into cache. */
36static void vbnv_setup(void)
37{
Arthur Heymans344e86b2019-11-20 19:47:10 +010038 if (!vbnv_initialized) {
39 read_vbnv(vbnv);
40 vbnv_initialized = 1;
Duncan Laurie88b28ad2016-01-25 17:13:27 -080041 }
42}
43
44/* Verify VBNV header and checksum. */
45int verify_vbnv(uint8_t *vbnv_copy)
46{
47 return (HEADER_SIGNATURE == (vbnv_copy[HEADER_OFFSET] & HEADER_MASK)) &&
48 (crc8_vbnv(vbnv_copy, CRC_OFFSET) == vbnv_copy[CRC_OFFSET]);
49}
50
Hung-Te Linfe2fc832016-12-29 20:59:37 +080051/* Re-generate VBNV checksum. */
52void regen_vbnv_crc(uint8_t *vbnv_copy)
53{
54 vbnv_copy[CRC_OFFSET] = crc8_vbnv(vbnv_copy, CRC_OFFSET);
55}
56
Furquan Shaikh165b6cf2016-06-27 16:19:09 -070057/*
58 * Read VBNV data from configured storage backend.
59 * If VBNV verification fails, reset the vbnv copy.
Furquan Shaikh165b6cf2016-06-27 16:19:09 -070060 */
Furquan Shaikhbe87f732016-06-29 11:26:27 -070061void read_vbnv(uint8_t *vbnv_copy)
Duncan Laurie88b28ad2016-01-25 17:13:27 -080062{
Julius Wernercd49cce2019-03-05 16:53:33 -080063 if (CONFIG(VBOOT_VBNV_CMOS))
Duncan Laurie88b28ad2016-01-25 17:13:27 -080064 read_vbnv_cmos(vbnv_copy);
Julius Wernercd49cce2019-03-05 16:53:33 -080065 else if (CONFIG(VBOOT_VBNV_FLASH))
Duncan Laurie88b28ad2016-01-25 17:13:27 -080066 read_vbnv_flash(vbnv_copy);
Yu-Ping Wu6b0d0852022-06-08 10:23:32 +080067 else
68 dead_code();
Duncan Laurie88b28ad2016-01-25 17:13:27 -080069
70 /* Check data for consistency */
Furquan Shaikhbe87f732016-06-29 11:26:27 -070071 if (!verify_vbnv(vbnv_copy))
Aaron Durbinfe265a12017-09-15 11:17:38 -060072 vbnv_reset(vbnv_copy);
Duncan Laurie88b28ad2016-01-25 17:13:27 -080073}
74
75/*
76 * Write VBNV data to configured storage backend.
77 * This assumes that the caller has updated the CRC already.
78 */
79void save_vbnv(const uint8_t *vbnv_copy)
80{
Julius Wernercd49cce2019-03-05 16:53:33 -080081 if (CONFIG(VBOOT_VBNV_CMOS))
Duncan Laurie88b28ad2016-01-25 17:13:27 -080082 save_vbnv_cmos(vbnv_copy);
Julius Wernercd49cce2019-03-05 16:53:33 -080083 else if (CONFIG(VBOOT_VBNV_FLASH))
Duncan Laurie88b28ad2016-01-25 17:13:27 -080084 save_vbnv_flash(vbnv_copy);
Yu-Ping Wu6b0d0852022-06-08 10:23:32 +080085 else
86 dead_code();
Duncan Laurie88b28ad2016-01-25 17:13:27 -080087
88 /* Clear initialized flag to force cached data to be updated */
Arthur Heymans344e86b2019-11-20 19:47:10 +010089 vbnv_initialized = 0;
Duncan Laurie88b28ad2016-01-25 17:13:27 -080090}
91
Furquan Shaikh37c721d2018-04-25 18:13:03 -070092/* Read the USB Device Controller(UDC) enable flag from VBNV. */
93int vbnv_udc_enable_flag(void)
94{
95 vbnv_setup();
Arthur Heymans344e86b2019-11-20 19:47:10 +010096 return (vbnv[DEV_FLAGS_OFFSET] & DEV_ENABLE_UDC) ? 1 : 0;
Furquan Shaikh37c721d2018-04-25 18:13:03 -070097}
98
Aaron Durbin118a84f2017-09-15 11:15:07 -060099void vbnv_init(uint8_t *vbnv_copy)
100{
Julius Wernercd49cce2019-03-05 16:53:33 -0800101 if (CONFIG(VBOOT_VBNV_CMOS))
Aaron Durbin0990fbf2017-09-15 15:23:04 -0600102 vbnv_init_cmos(vbnv_copy);
Aaron Durbin118a84f2017-09-15 11:15:07 -0600103 read_vbnv(vbnv_copy);
104}