blob: 207aadaac7c4a4e6f2262c7fd48b43e7c893fa16 [file] [log] [blame]
Aaron Durbin17200ad2015-05-01 16:48:54 -05001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2015 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.
Aaron Durbin17200ad2015-05-01 16:48:54 -050014 */
15
Aaron Durbin6d720f32015-12-08 17:00:23 -060016#include <arch/early_variables.h>
Aaron Durbin17200ad2015-05-01 16:48:54 -050017#include <cbfs.h>
Aaron Durbin09560fa2015-05-12 16:43:10 -050018#include <cbmem.h>
Aaron Durbin17200ad2015-05-01 16:48:54 -050019#include <console/console.h>
Aaron Durbinf7ce40b2016-08-24 14:58:12 -050020#include <ec/google/chromeec/ec.h>
Aaron Durbin09560fa2015-05-12 16:43:10 -050021#include <rmodule.h>
Aaron Durbin17200ad2015-05-01 16:48:54 -050022#include <rules.h>
23#include <string.h>
Furquan Shaikh2a12e2e2016-07-25 11:48:03 -070024#include <vboot/misc.h>
25#include <vboot/symbols.h>
26#include <vboot/vboot_common.h>
Aaron Durbin17200ad2015-05-01 16:48:54 -050027
28/* The stage loading code is compiled and entered from multiple stages. The
29 * helper functions below attempt to provide more clarity on when certain
30 * code should be called. */
31
32static int verification_should_run(void)
33{
34 if (ENV_VERSTAGE && IS_ENABLED(CONFIG_SEPARATE_VERSTAGE))
35 return 1;
36
37 if (!IS_ENABLED(CONFIG_SEPARATE_VERSTAGE)) {
38 if (ENV_ROMSTAGE &&
39 IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE))
40 return 1;
41 if (ENV_BOOTBLOCK &&
42 IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK))
43 return 1;
44 }
45
46 return 0;
47}
48
49static int verstage_should_load(void)
50{
51 if (!IS_ENABLED(CONFIG_SEPARATE_VERSTAGE))
52 return 0;
53
54 if (ENV_ROMSTAGE && IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE))
55 return 1;
56
57 if (ENV_BOOTBLOCK && IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK))
58 return 1;
59
60 return 0;
61}
62
Aaron Durbin6d720f32015-12-08 17:00:23 -060063static int vboot_executed CAR_GLOBAL;
64
Furquan Shaikha6c5ddd2016-07-22 06:59:40 -070065int vb2_logic_executed(void)
Aaron Durbin6d720f32015-12-08 17:00:23 -060066{
67 /* If this stage is supposed to run the vboot logic ensure it has been
68 * executed. */
69 if (verification_should_run() && car_get_var(vboot_executed))
70 return 1;
71
72 /* If this stage is supposed to load verstage and verstage is returning
73 * back to the calling stage check that it has been executed. */
74 if (verstage_should_load() && IS_ENABLED(CONFIG_RETURN_FROM_VERSTAGE))
75 if (car_get_var(vboot_executed))
76 return 1;
77
78 /* Handle all other stages post vboot execution. */
79 if (!ENV_BOOTBLOCK) {
80 if (IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK))
81 return 1;
82 if (IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE) &&
83 !ENV_ROMSTAGE)
84 return 1;
85 }
86
87 return 0;
88}
89
90static void vboot_prepare(void)
Aaron Durbin17200ad2015-05-01 16:48:54 -050091{
Paul Kocialkowski18117682016-05-14 15:30:52 +020092 if (verification_should_run()) {
Aaron Durbinf7ce40b2016-08-24 14:58:12 -050093 /*
94 * Note that this path isn't taken when
95 * CONFIG_RETURN_FROM_VERSTAGE is employed.
96 */
Aaron Durbin17200ad2015-05-01 16:48:54 -050097 verstage_main();
Aaron Durbin6d720f32015-12-08 17:00:23 -060098 car_set_var(vboot_executed, 1);
Furquan Shaikh85aa1352016-07-22 08:56:43 -070099 vb2_save_recovery_reason_vbnv();
Aaron Durbinf7ce40b2016-08-24 14:58:12 -0500100
101 /*
102 * Avoid double memory retrain when the EC is running RW code
103 * and a recovery request came in through an EC host event. The
104 * double retrain happens because the EC won't be rebooted
105 * until kernel verification notices the EC isn't running RO
106 * code which is after memory training. Therefore, reboot the
107 * EC after we've saved the potential recovery request so it's
108 * not lost. Lastly, only perform this sequence on x86
109 * platforms since those are the ones that currently do a
110 * costly memory training in recovery mode.
111 */
112 if (IS_ENABLED(CONFIG_EC_GOOGLE_CHROMEEC) &&
113 IS_ENABLED(CONFIG_ARCH_X86))
114 google_chromeec_early_init();
115
Aaron Durbin17200ad2015-05-01 16:48:54 -0500116 } else if (verstage_should_load()) {
Aaron Durbin37a5d152015-09-17 16:09:30 -0500117 struct cbfsf file;
Aaron Durbinac12c66c2015-05-20 12:08:55 -0500118 struct prog verstage =
Aaron Durbin7e7a4df2015-12-08 14:34:35 -0600119 PROG_INIT(PROG_VERSTAGE,
Aaron Durbinac12c66c2015-05-20 12:08:55 -0500120 CONFIG_CBFS_PREFIX "/verstage");
Aaron Durbin17200ad2015-05-01 16:48:54 -0500121
Aaron Durbince2c50d2015-05-13 13:33:27 -0500122 printk(BIOS_DEBUG, "VBOOT: Loading verstage.\n");
123
Aaron Durbin17200ad2015-05-01 16:48:54 -0500124 /* load verstage from RO */
Aaron Durbin37a5d152015-09-17 16:09:30 -0500125 if (cbfs_boot_locate(&file, prog_name(&verstage), NULL))
126 die("failed to load verstage");
127
128 cbfs_file_data(prog_rdev(&verstage), &file);
129
130 if (cbfs_prog_stage_load(&verstage))
Aaron Durbin17200ad2015-05-01 16:48:54 -0500131 die("failed to load verstage");
132
133 /* verify and select a slot */
134 prog_run(&verstage);
135
136 /* This is not actually possible to hit this condition at
137 * runtime, but this provides a hint to the compiler for dead
138 * code elimination below. */
139 if (!IS_ENABLED(CONFIG_RETURN_FROM_VERSTAGE))
Aaron Durbin6d720f32015-12-08 17:00:23 -0600140 return;
141
142 car_set_var(vboot_executed, 1);
Aaron Durbin17200ad2015-05-01 16:48:54 -0500143 }
144
Aaron Durbinb5933662015-10-07 16:03:41 -0500145 /*
146 * Fill in vboot cbmem objects before moving to ramstage so all
147 * downstream users have access to vboot results. This path only
148 * applies to platforms employing VBOOT_DYNAMIC_WORK_BUFFER because
149 * cbmem comes online prior to vboot verification taking place. For
150 * other platforms the vboot cbmem objects are initialized when
151 * cbmem comes online.
152 */
153 if (ENV_ROMSTAGE && IS_ENABLED(CONFIG_VBOOT_DYNAMIC_WORK_BUFFER)) {
154 vb2_store_selected_region();
Aaron Durbin17200ad2015-05-01 16:48:54 -0500155 vboot_fill_handoff();
Aaron Durbinb5933662015-10-07 16:03:41 -0500156 }
Aaron Durbin17200ad2015-05-01 16:48:54 -0500157}
158
Aaron Durbin6d720f32015-12-08 17:00:23 -0600159static int vboot_locate(struct cbfs_props *props)
Aaron Durbin17200ad2015-05-01 16:48:54 -0500160{
Aaron Durbin6d720f32015-12-08 17:00:23 -0600161 struct region selected_region;
Aaron Durbin899d13d2015-05-15 23:39:23 -0500162
Aaron Durbin6d720f32015-12-08 17:00:23 -0600163 /* Don't honor vboot results until the vboot logic has run. */
Furquan Shaikha6c5ddd2016-07-22 06:59:40 -0700164 if (!vb2_logic_executed())
Aaron Durbinb6981c02015-05-15 15:57:51 -0500165 return -1;
Aaron Durbin17200ad2015-05-01 16:48:54 -0500166
Aaron Durbin6d720f32015-12-08 17:00:23 -0600167 if (vb2_get_selected_region(&selected_region))
Aaron Durbin4e50cdd2015-05-15 23:25:46 -0500168 return -1;
Aaron Durbinb6981c02015-05-15 15:57:51 -0500169
Aaron Durbin6d720f32015-12-08 17:00:23 -0600170 props->offset = region_offset(&selected_region);
171 props->size = region_sz(&selected_region);
Aaron Durbin17200ad2015-05-01 16:48:54 -0500172
Aaron Durbinb6981c02015-05-15 15:57:51 -0500173 return 0;
Aaron Durbin17200ad2015-05-01 16:48:54 -0500174}
175
Aaron Durbin6d720f32015-12-08 17:00:23 -0600176const struct cbfs_locator vboot_locator = {
Aaron Durbin17200ad2015-05-01 16:48:54 -0500177 .name = "VBOOT",
Aaron Durbin6d720f32015-12-08 17:00:23 -0600178 .prepare = vboot_prepare,
Aaron Durbin899d13d2015-05-15 23:39:23 -0500179 .locate = vboot_locate,
Aaron Durbin17200ad2015-05-01 16:48:54 -0500180};