coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
vbnv_cmos.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <bootstate.h>
4 #include <boot/coreboot_tables.h>
5 #include <console/console.h>
6 #include <types.h>
7 #include <pc80/mc146818rtc.h>
8 #include <security/vboot/vbnv.h>
10 
11 static void clear_vbnv_battery_cutoff_flag(uint8_t *vbnv_copy)
12 {
13  /*
14  * Currently battery cutoff is done in payload stage, which does not
15  * update backup VBNV. And doing battery cutoff will invalidate CMOS.
16  * This means for every reboot after cutoff, read_vbnv_cmos will reload
17  * backup VBNV and try to cutoff again, causing endless reboot loop.
18  * So we should always clear battery cutoff flag from loaded backup.
19  */
21  printk(BIOS_INFO, "VBNV: Remove battery cut-off request.\n");
23  regen_vbnv_crc(vbnv_copy);
24  }
25 }
26 
27 /* Return non-zero if backup was used. */
28 static int restore_from_backup(uint8_t *vbnv_copy)
29 {
30  if (!CONFIG(VBOOT_VBNV_CMOS_BACKUP_TO_FLASH))
31  return 0;
32 
33  printk(BIOS_INFO, "VBNV: CMOS invalid, restoring from flash\n");
34  read_vbnv_flash(vbnv_copy);
35 
36  if (verify_vbnv(vbnv_copy)) {
38  save_vbnv_cmos(vbnv_copy);
39  printk(BIOS_INFO, "VBNV: Flash backup restored\n");
40  return 1;
41  }
42 
43  printk(BIOS_INFO, "VBNV: Restore from flash failed\n");
44 
45  return 0;
46 }
47 
48 void read_vbnv_cmos(uint8_t *vbnv_copy)
49 {
50  int i;
51 
52  for (i = 0; i < VBOOT_VBNV_BLOCK_SIZE; i++)
53  vbnv_copy[i] = cmos_read(CONFIG_VBOOT_VBNV_OFFSET + 14 + i);
54 
55  /* Verify contents before attempting a restore from backup storage. */
56  if (verify_vbnv(vbnv_copy))
57  return;
58 
59  restore_from_backup(vbnv_copy);
60 }
61 
62 void save_vbnv_cmos(const uint8_t *vbnv_copy)
63 {
64  int i;
65 
66  for (i = 0; i < VBOOT_VBNV_BLOCK_SIZE; i++)
67  cmos_write(vbnv_copy[i], CONFIG_VBOOT_VBNV_OFFSET + 14 + i);
68 }
69 
70 void vbnv_init_cmos(uint8_t *vbnv_copy)
71 {
72  /* If no CMOS failure just defer to the normal read path for checking
73  vbnv contents' integrity. */
74  if (!vbnv_cmos_failed())
75  return;
76 
77  /* In the case of CMOS failure force the backup. If backup wasn't used
78  force the vbnv CMOS to be reset. */
79  if (!restore_from_backup(vbnv_copy)) {
80  vbnv_reset(vbnv_copy);
81  /* This parallels the vboot_reference implementation. */
82  vbnv_copy[HEADER_OFFSET] = HEADER_SIGNATURE |
85  regen_vbnv_crc(vbnv_copy);
86  save_vbnv_cmos(vbnv_copy);
87  }
88 }
89 
91 {
92  struct lb_range *vbnv;
93 
94  vbnv = (struct lb_range *)lb_new_record(header);
95  vbnv->tag = LB_TAG_VBNV;
96  vbnv->size = sizeof(*vbnv);
97  vbnv->range_start = CONFIG_VBOOT_VBNV_OFFSET + 14;
98  vbnv->range_size = VBOOT_VBNV_BLOCK_SIZE;
99 }
100 
101 #if CONFIG(VBOOT_VBNV_CMOS_BACKUP_TO_FLASH)
102 static void back_up_vbnv_cmos(void *unused)
103 {
104  uint8_t vbnv_cmos[VBOOT_VBNV_BLOCK_SIZE];
105 
106  /* Read current VBNV from CMOS. */
107  read_vbnv_cmos(vbnv_cmos);
108 
109  /* Save to flash, will only be saved if different. */
110  save_vbnv_flash(vbnv_cmos);
111 }
113 #endif
struct arm64_kernel_header header
Definition: fit_payload.c:30
#define BOOT_STATE_INIT_ENTRY(state_, when_, func_, arg_)
Definition: bootstate.h:182
@ BS_POST_DEVICE
Definition: bootstate.h:84
@ BS_ON_EXIT
Definition: bootstate.h:96
@ LB_TAG_VBNV
#define printk(level,...)
Definition: stdlib.h:16
@ CONFIG
Definition: dsi_common.h:201
struct lb_record * lb_new_record(struct lb_header *header)
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
static void cmos_write(unsigned char val, unsigned char addr)
Definition: mc146818rtc.h:141
static unsigned char cmos_read(unsigned char addr)
Definition: mc146818rtc.h:105
static int restore_from_backup(uint8_t *vbnv_copy)
Definition: vbnv_cmos.c:28
void read_vbnv_cmos(uint8_t *vbnv_copy)
Definition: vbnv_cmos.c:48
void vbnv_init_cmos(uint8_t *vbnv_copy)
Definition: vbnv_cmos.c:70
void lb_table_add_vbnv_cmos(struct lb_header *header)
Definition: vbnv_cmos.c:90
static void clear_vbnv_battery_cutoff_flag(uint8_t *vbnv_copy)
Definition: vbnv_cmos.c:11
void save_vbnv_cmos(const uint8_t *vbnv_copy)
Definition: vbnv_cmos.c:62
int vbnv_cmos_failed(void)
Definition: vbnv_cmos.c:6
#define NULL
Definition: stddef.h:19
unsigned char uint8_t
Definition: stdint.h:8
void vbnv_reset(uint8_t *vbnv_copy)
Definition: vbnv.c:29
static uint8_t vbnv[VBOOT_VBNV_BLOCK_SIZE]
Definition: vbnv.c:9
void regen_vbnv_crc(uint8_t *vbnv_copy)
Definition: vbnv.c:51
int verify_vbnv(uint8_t *vbnv_copy)
Definition: vbnv.c:44
void read_vbnv_flash(uint8_t *vbnv_copy)
Definition: vbnv_flash.c:117
void save_vbnv_flash(const uint8_t *vbnv_copy)
Definition: vbnv_flash.c:128
#define HEADER_SIGNATURE
Definition: vbnv_layout.h:14
#define MISC_FLAGS_OFFSET
Definition: vbnv_layout.h:32
#define HEADER_OFFSET
Definition: vbnv_layout.h:12
#define VBOOT_VBNV_BLOCK_SIZE
Definition: vbnv_layout.h:6
#define MISC_FLAGS_BATTERY_CUTOFF_MASK
Definition: vbnv_layout.h:33
#define HEADER_KERNEL_SETTINGS_RESET
Definition: vbnv_layout.h:16
#define HEADER_FIRMWARE_SETTINGS_RESET
Definition: vbnv_layout.h:15