blob: 4625bcdff24e6c3ca174fcb243d6f9502d6adb16 [file] [log] [blame]
Furquan Shaikh6d448e32016-07-22 08:28:57 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 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
Joel Kitching4114aa82019-04-25 17:10:52 +080016#define NEED_VB20_INTERNALS /* Peeking into vb2_shared_data */
17
Furquan Shaikh6d448e32016-07-22 08:28:57 -070018#include <assert.h>
Furquan Shaikh2a12e2e2016-07-25 11:48:03 -070019#include <bootmode.h>
Furquan Shaikh85aa1352016-07-22 08:56:43 -070020#include <bootstate.h>
Aaron Durbinb2a5f482016-12-14 14:40:43 -060021#include <cbmem.h>
Furquan Shaikh6d448e32016-07-22 08:28:57 -070022#include <vb2_api.h>
Philipp Deppenwiesefea24292017-10-17 17:02:29 +020023#include <security/vboot/misc.h>
24#include <security/vboot/vbnv.h>
25#include <security/vboot/vboot_common.h>
Furquan Shaikh6d448e32016-07-22 08:28:57 -070026
Joel Kitchingaf8471c2019-03-13 22:38:07 +080027static int vboot_get_recovery_reason_shared_data(void)
Furquan Shaikh6d448e32016-07-22 08:28:57 -070028{
Joel Kitchingaf8471c2019-03-13 22:38:07 +080029 struct vb2_shared_data *sd = vboot_get_shared_data();
Furquan Shaikh6d448e32016-07-22 08:28:57 -070030 assert(sd);
31 return sd->recovery_reason;
32}
33
Joel Kitchingaf8471c2019-03-13 22:38:07 +080034void vboot_save_recovery_reason_vbnv(void)
Furquan Shaikh85aa1352016-07-22 08:56:43 -070035{
Julius Wernercd49cce2019-03-05 16:53:33 -080036 if (!CONFIG(VBOOT_SAVE_RECOVERY_REASON_ON_REBOOT))
Furquan Shaikh85aa1352016-07-22 08:56:43 -070037 return;
38
Joel Kitchingaf8471c2019-03-13 22:38:07 +080039 int reason = vboot_get_recovery_reason_shared_data();
Furquan Shaikh85aa1352016-07-22 08:56:43 -070040 if (!reason)
41 return;
42
43 set_recovery_mode_into_vbnv(reason);
44}
45
Joel Kitching7b10deb2019-06-17 15:22:28 +080046static void vboot_clear_recovery_reason_vbnv(void *unused)
Furquan Shaikh85aa1352016-07-22 08:56:43 -070047{
Julius Wernercd49cce2019-03-05 16:53:33 -080048 if (!CONFIG(VBOOT_SAVE_RECOVERY_REASON_ON_REBOOT))
Furquan Shaikh85aa1352016-07-22 08:56:43 -070049 return;
50
51 set_recovery_mode_into_vbnv(0);
52}
53
54/*
55 * Recovery reason stored in VBNV needs to be cleared before the state of VBNV
56 * is backed-up anywhere or jumping to the payload (whichever occurs
57 * first). Currently, vbnv_cmos.c backs up VBNV on POST_DEVICE. Thus, we need to
58 * make sure that the stored recovery reason is cleared off before that
59 * happens.
60 * IMPORTANT: Any reboot occurring after BS_DEV_INIT state will cause loss of
Elyes HAOUASbc0ec502018-08-07 12:15:54 +020061 * recovery reason on reboot. Until now, we have seen reboots occurring on x86
Furquan Shaikh85aa1352016-07-22 08:56:43 -070062 * only in FSP stages which run before BS_DEV_INIT.
63 */
64BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_EXIT,
Joel Kitching7b10deb2019-06-17 15:22:28 +080065 vboot_clear_recovery_reason_vbnv, NULL);
Furquan Shaikh85aa1352016-07-22 08:56:43 -070066
Furquan Shaikh6d448e32016-07-22 08:28:57 -070067/*
Furquan Shaikh6d448e32016-07-22 08:28:57 -070068 * Returns 1 if vboot is being used and currently in a stage which might have
69 * already executed vboot verification.
70 */
71static int vboot_possibly_executed(void)
72{
Julius Wernercd49cce2019-03-05 16:53:33 -080073 if (CONFIG(VBOOT_STARTS_IN_BOOTBLOCK)) {
74 if (ENV_BOOTBLOCK && CONFIG(VBOOT_SEPARATE_VERSTAGE))
Furquan Shaikh6d448e32016-07-22 08:28:57 -070075 return 0;
76 return 1;
77 }
78
Julius Wernercd49cce2019-03-05 16:53:33 -080079 if (CONFIG(VBOOT_STARTS_IN_ROMSTAGE)) {
Furquan Shaikh6d448e32016-07-22 08:28:57 -070080 if (ENV_BOOTBLOCK)
81 return 0;
82 return 1;
83 }
84
85 return 0;
86}
87
88/*
89 * vb2_check_recovery_request looks up different components to identify if there
90 * is a recovery request and returns appropriate reason code:
91 * 1. Checks if recovery mode is initiated by EC. If yes, returns
92 * VB2_RECOVERY_RO_MANUAL.
93 * 2. Checks if recovery request is present in VBNV and returns the code read
94 * from it.
Joel Kitchinga06cd6c2019-06-16 16:44:26 +080095 * 3. Checks if vboot verification is done and looks up selected region
96 * to identify if vboot_reference library has requested recovery path.
97 * If yes, return the reason code from shared data.
98 * 4. If nothing applies, return 0 indicating no recovery request.
Furquan Shaikh6d448e32016-07-22 08:28:57 -070099 */
100int vboot_check_recovery_request(void)
101{
102 int reason = 0;
103
104 /* EC-initiated recovery. */
105 if (get_recovery_mode_switch())
106 return VB2_RECOVERY_RO_MANUAL;
107
108 /* Recovery request in VBNV. */
109 if ((reason = get_recovery_mode_from_vbnv()) != 0)
110 return reason;
111
112 /*
Joel Kitchinga06cd6c2019-06-16 16:44:26 +0800113 * Identify if vboot verification is already complete and no slot
114 * was selected i.e. recovery path was requested.
Furquan Shaikh6d448e32016-07-22 08:28:57 -0700115 */
Joel Kitchingaf8471c2019-03-13 22:38:07 +0800116 if (vboot_possibly_executed() && vboot_logic_executed() &&
117 !vboot_is_slot_selected())
118 return vboot_get_recovery_reason_shared_data();
Furquan Shaikh6d448e32016-07-22 08:28:57 -0700119
120 return 0;
121}
Furquan Shaikh0325dc62016-07-25 13:02:36 -0700122
123int vboot_recovery_mode_enabled(void)
124{
Furquan Shaikh0325dc62016-07-25 13:02:36 -0700125 return !!vboot_check_recovery_request();
126}
127
Aaron Durbin64031672018-04-21 14:45:32 -0600128int __weak clear_recovery_mode_switch(void)
Julius Werner58c39382017-02-13 17:53:29 -0800129{
130 // Weak implementation. Nothing to do.
131 return 0;
132}
133
Aaron Durbin64031672018-04-21 14:45:32 -0600134void __weak log_recovery_mode_switch(void)
Julius Werner58c39382017-02-13 17:53:29 -0800135{
136 // Weak implementation. Nothing to do.
137}
138
Aaron Durbin64031672018-04-21 14:45:32 -0600139int __weak get_recovery_mode_retrain_switch(void)
Furquan Shaikh470852b2016-11-05 23:52:08 -0700140{
141 return 0;
142}
143
144int vboot_recovery_mode_memory_retrain(void)
145{
146 return get_recovery_mode_retrain_switch();
147}
148
Furquan Shaikh0325dc62016-07-25 13:02:36 -0700149int vboot_developer_mode_enabled(void)
150{
Joel Kitching7576bd72019-05-17 14:26:01 +0800151 return cbmem_possibly_online() &&
152 vboot_get_working_data()->flags & VBOOT_WD_FLAG_DEVELOPER_MODE;
Furquan Shaikh0325dc62016-07-25 13:02:36 -0700153}
Philipp Deppenwiese7410f8b2017-10-18 15:29:26 +0200154
Julius Wernercd49cce2019-03-05 16:53:33 -0800155#if CONFIG(VBOOT_NO_BOARD_SUPPORT)
Philipp Deppenwiese7410f8b2017-10-18 15:29:26 +0200156/**
157 * TODO: Create flash protection interface which implements get_write_protect_state.
158 * get_recovery_mode_switch should be implemented as default function.
159 */
Aaron Durbin64031672018-04-21 14:45:32 -0600160int __weak get_write_protect_state(void)
Philipp Deppenwiese7410f8b2017-10-18 15:29:26 +0200161{
162 return 0;
163}
164
Aaron Durbin64031672018-04-21 14:45:32 -0600165int __weak get_recovery_mode_switch(void)
Philipp Deppenwiese7410f8b2017-10-18 15:29:26 +0200166{
167 return 0;
168}
169
170#endif