drivers/wifi: Remove unnecessary data structure copy
[coreboot2.git] / src / security / vboot / vbnv_cmos.c
blob5073509fc9cd09f8a612b0578b242b36cf876087
1 /* SPDX-License-Identifier: GPL-2.0-only */
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>
9 #include <security/vboot/vbnv_layout.h>
11 static void clear_vbnv_battery_cutoff_flag(uint8_t *vbnv_copy)
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.
20 if (vbnv_copy[MISC_FLAGS_OFFSET] & MISC_FLAGS_BATTERY_CUTOFF_MASK) {
21 printk(BIOS_INFO, "VBNV: Remove battery cut-off request.\n");
22 vbnv_copy[MISC_FLAGS_OFFSET] &= ~MISC_FLAGS_BATTERY_CUTOFF_MASK;
23 regen_vbnv_crc(vbnv_copy);
27 /* Return non-zero if backup was used. */
28 static int restore_from_backup(uint8_t *vbnv_copy)
30 if (!CONFIG(VBOOT_VBNV_CMOS_BACKUP_TO_FLASH))
31 return 0;
33 printk(BIOS_INFO, "VBNV: CMOS invalid, restoring from flash\n");
34 read_vbnv_flash(vbnv_copy);
36 if (verify_vbnv(vbnv_copy)) {
37 clear_vbnv_battery_cutoff_flag(vbnv_copy);
38 save_vbnv_cmos(vbnv_copy);
39 printk(BIOS_INFO, "VBNV: Flash backup restored\n");
40 return 1;
43 printk(BIOS_INFO, "VBNV: Restore from flash failed\n");
45 return 0;
48 void read_vbnv_cmos(uint8_t *vbnv_copy)
50 int i;
52 for (i = 0; i < VBOOT_VBNV_BLOCK_SIZE; i++)
53 vbnv_copy[i] = cmos_read(CONFIG_VBOOT_VBNV_OFFSET + 14 + i);
55 /* Verify contents before attempting a restore from backup storage. */
56 if (verify_vbnv(vbnv_copy))
57 return;
59 restore_from_backup(vbnv_copy);
62 void save_vbnv_cmos(const uint8_t *vbnv_copy)
64 int i;
66 for (i = 0; i < VBOOT_VBNV_BLOCK_SIZE; i++)
67 cmos_write(vbnv_copy[i], CONFIG_VBOOT_VBNV_OFFSET + 14 + i);
70 void __weak vbnv_platform_init_cmos(void)
74 void vbnv_init_cmos(uint8_t *vbnv_copy)
76 vbnv_platform_init_cmos();
78 /* If no CMOS failure just defer to the normal read path for checking
79 vbnv contents' integrity. */
80 if (!vbnv_cmos_failed())
81 return;
83 /* In the case of CMOS failure force the backup. If backup wasn't used
84 force the vbnv CMOS to be reset. */
85 if (!restore_from_backup(vbnv_copy)) {
86 vbnv_reset(vbnv_copy);
87 /* This parallels the vboot_reference implementation. */
88 vbnv_copy[HEADER_OFFSET] = HEADER_SIGNATURE |
89 HEADER_FIRMWARE_SETTINGS_RESET |
90 HEADER_KERNEL_SETTINGS_RESET;
91 regen_vbnv_crc(vbnv_copy);
92 save_vbnv_cmos(vbnv_copy);
96 void lb_table_add_vbnv_cmos(struct lb_header *header)
98 struct lb_range *vbnv;
100 vbnv = (struct lb_range *)lb_new_record(header);
101 vbnv->tag = LB_TAG_VBNV;
102 vbnv->size = sizeof(*vbnv);
103 vbnv->range_start = CONFIG_VBOOT_VBNV_OFFSET + 14;
104 vbnv->range_size = VBOOT_VBNV_BLOCK_SIZE;
107 #if CONFIG(VBOOT_VBNV_CMOS_BACKUP_TO_FLASH)
108 static void back_up_vbnv_cmos(void *unused)
110 uint8_t vbnv_cmos[VBOOT_VBNV_BLOCK_SIZE];
112 /* Read current VBNV from CMOS. */
113 read_vbnv_cmos(vbnv_cmos);
115 /* Save to flash, will only be saved if different. */
116 save_vbnv_flash(vbnv_cmos);
118 BOOT_STATE_INIT_ENTRY(BS_POST_DEVICE, BS_ON_EXIT, back_up_vbnv_cmos, NULL);
119 #endif