blob: b7ef3e767fd10d721b3cebf2843e2d54ef0c0aa1 [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
Duncan Lauriefe970132016-01-26 16:30:36 -080016#include <bootstate.h>
17#include <console/console.h>
Stefan Reinauer9aea04a2012-03-30 12:01:06 -070018#include <types.h>
Stefan Reinauer9aea04a2012-03-30 12:01:06 -070019#include <pc80/mc146818rtc.h>
Furquan Shaikh2a12e2e2016-07-25 11:48:03 -070020#include <vboot/vbnv.h>
21#include <vboot/vbnv_layout.h>
Stefan Reinauer9aea04a2012-03-30 12:01:06 -070022
Hung-Te Linfe2fc832016-12-29 20:59:37 +080023static void clear_vbnv_battery_cutoff_flag(uint8_t *vbnv_copy)
24{
25 /*
26 * Currently battery cutoff is done in payload stage, which does not
27 * update backup VBNV. And doing battery cutoff will invalidate CMOS.
28 * This means for every reboot after cutoff, read_vbnv_cmos will reload
29 * backup VBNV and try to cutoff again, causing endless reboot loop.
30 * So we should always clear battery cutoff flag from loaded backup.
31 */
32 if (vbnv_copy[MISC_FLAGS_OFFSET] & MISC_FLAGS_BATTERY_CUTOFF_MASK) {
33 printk(BIOS_INFO, "VBNV: Remove battery cut-off request.\n");
34 vbnv_copy[MISC_FLAGS_OFFSET] &= ~MISC_FLAGS_BATTERY_CUTOFF_MASK;
35 regen_vbnv_crc(vbnv_copy);
36 }
37}
38
Duncan Laurie88b28ad2016-01-25 17:13:27 -080039void read_vbnv_cmos(uint8_t *vbnv_copy)
Stefan Reinauer9aea04a2012-03-30 12:01:06 -070040{
41 int i;
42
Furquan Shaikh2a12e2e2016-07-25 11:48:03 -070043 for (i = 0; i < VBOOT_VBNV_BLOCK_SIZE; i++)
44 vbnv_copy[i] = cmos_read(CONFIG_VBOOT_VBNV_OFFSET + 14 + i);
Duncan Lauriefe970132016-01-26 16:30:36 -080045
Furquan Shaikh2a12e2e2016-07-25 11:48:03 -070046 if (IS_ENABLED(CONFIG_VBOOT_VBNV_CMOS_BACKUP_TO_FLASH)) {
Duncan Lauriefe970132016-01-26 16:30:36 -080047 if (verify_vbnv(vbnv_copy))
48 return;
49
50 printk(BIOS_INFO, "VBNV: CMOS invalid, restoring from flash\n");
51 read_vbnv_flash(vbnv_copy);
52
53 if (verify_vbnv(vbnv_copy)) {
Hung-Te Linfe2fc832016-12-29 20:59:37 +080054 clear_vbnv_battery_cutoff_flag(vbnv_copy);
Duncan Lauriefe970132016-01-26 16:30:36 -080055 save_vbnv_cmos(vbnv_copy);
56 printk(BIOS_INFO, "VBNV: Flash backup restored\n");
57 } else {
58 printk(BIOS_INFO, "VBNV: Restore from flash failed\n");
59 }
60 }
Aaron Durbinfd795622013-03-01 17:12:26 -060061}
62
Duncan Laurie88b28ad2016-01-25 17:13:27 -080063void save_vbnv_cmos(const uint8_t *vbnv_copy)
Aaron Durbinfd795622013-03-01 17:12:26 -060064{
65 int i;
66
Furquan Shaikh2a12e2e2016-07-25 11:48:03 -070067 for (i = 0; i < VBOOT_VBNV_BLOCK_SIZE; i++)
68 cmos_write(vbnv_copy[i], CONFIG_VBOOT_VBNV_OFFSET + 14 + i);
Aaron Durbinfd795622013-03-01 17:12:26 -060069}
Duncan Lauriefe970132016-01-26 16:30:36 -080070
Jagadish Krishnamoorthye2e561d2016-05-18 15:18:58 -070071void init_vbnv_cmos(int rtc_fail)
72{
Furquan Shaikh2a12e2e2016-07-25 11:48:03 -070073 uint8_t vbnv[VBOOT_VBNV_BLOCK_SIZE];
Jagadish Krishnamoorthye2e561d2016-05-18 15:18:58 -070074
75 if (rtc_fail)
76 read_vbnv_cmos(vbnv);
77
78 cmos_init(rtc_fail);
79
80 if (rtc_fail)
81 save_vbnv_cmos(vbnv);
82}
83
Furquan Shaikh2a12e2e2016-07-25 11:48:03 -070084#if IS_ENABLED(CONFIG_VBOOT_VBNV_CMOS_BACKUP_TO_FLASH)
Patrick Georgi6b881b22016-02-09 14:01:08 +010085static void back_up_vbnv_cmos(void *unused)
Duncan Lauriefe970132016-01-26 16:30:36 -080086{
Furquan Shaikh2a12e2e2016-07-25 11:48:03 -070087 uint8_t vbnv_cmos[VBOOT_VBNV_BLOCK_SIZE];
Duncan Lauriefe970132016-01-26 16:30:36 -080088
89 /* Read current VBNV from CMOS. */
90 read_vbnv_cmos(vbnv_cmos);
91
92 /* Save to flash, will only be saved if different. */
93 save_vbnv_flash(vbnv_cmos);
94}
Patrick Georgi6b881b22016-02-09 14:01:08 +010095BOOT_STATE_INIT_ENTRY(BS_POST_DEVICE, BS_ON_EXIT, back_up_vbnv_cmos, NULL);
Duncan Lauriefe970132016-01-26 16:30:36 -080096#endif