blob: b76d20bebe4aa51572c9e47c39bdc7bca3add01f [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 Durbin09560fa2015-05-12 16:43:10 -050020#include <rmodule.h>
Aaron Durbin17200ad2015-05-01 16:48:54 -050021#include <rules.h>
22#include <string.h>
23#include "misc.h"
Furquan Shaikha6c5ddd2016-07-22 06:59:40 -070024#include "../vboot_common.h"
Aaron Durbin17200ad2015-05-01 16:48:54 -050025#include "../symbols.h"
26
27/* The stage loading code is compiled and entered from multiple stages. The
28 * helper functions below attempt to provide more clarity on when certain
29 * code should be called. */
30
31static int verification_should_run(void)
32{
33 if (ENV_VERSTAGE && IS_ENABLED(CONFIG_SEPARATE_VERSTAGE))
34 return 1;
35
36 if (!IS_ENABLED(CONFIG_SEPARATE_VERSTAGE)) {
37 if (ENV_ROMSTAGE &&
38 IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE))
39 return 1;
40 if (ENV_BOOTBLOCK &&
41 IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK))
42 return 1;
43 }
44
45 return 0;
46}
47
48static int verstage_should_load(void)
49{
50 if (!IS_ENABLED(CONFIG_SEPARATE_VERSTAGE))
51 return 0;
52
53 if (ENV_ROMSTAGE && IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE))
54 return 1;
55
56 if (ENV_BOOTBLOCK && IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK))
57 return 1;
58
59 return 0;
60}
61
Aaron Durbin6d720f32015-12-08 17:00:23 -060062static int vboot_executed CAR_GLOBAL;
63
Furquan Shaikha6c5ddd2016-07-22 06:59:40 -070064int vb2_logic_executed(void)
Aaron Durbin6d720f32015-12-08 17:00:23 -060065{
66 /* If this stage is supposed to run the vboot logic ensure it has been
67 * executed. */
68 if (verification_should_run() && car_get_var(vboot_executed))
69 return 1;
70
71 /* If this stage is supposed to load verstage and verstage is returning
72 * back to the calling stage check that it has been executed. */
73 if (verstage_should_load() && IS_ENABLED(CONFIG_RETURN_FROM_VERSTAGE))
74 if (car_get_var(vboot_executed))
75 return 1;
76
77 /* Handle all other stages post vboot execution. */
78 if (!ENV_BOOTBLOCK) {
79 if (IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK))
80 return 1;
81 if (IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE) &&
82 !ENV_ROMSTAGE)
83 return 1;
84 }
85
86 return 0;
87}
88
89static void vboot_prepare(void)
Aaron Durbin17200ad2015-05-01 16:48:54 -050090{
Paul Kocialkowski18117682016-05-14 15:30:52 +020091 if (verification_should_run()) {
Aaron Durbin17200ad2015-05-01 16:48:54 -050092 verstage_main();
Aaron Durbin6d720f32015-12-08 17:00:23 -060093 car_set_var(vboot_executed, 1);
Furquan Shaikh85aa1352016-07-22 08:56:43 -070094 vb2_save_recovery_reason_vbnv();
Aaron Durbin17200ad2015-05-01 16:48:54 -050095 } else if (verstage_should_load()) {
Aaron Durbin37a5d152015-09-17 16:09:30 -050096 struct cbfsf file;
Aaron Durbinac12c66c2015-05-20 12:08:55 -050097 struct prog verstage =
Aaron Durbin7e7a4df2015-12-08 14:34:35 -060098 PROG_INIT(PROG_VERSTAGE,
Aaron Durbinac12c66c2015-05-20 12:08:55 -050099 CONFIG_CBFS_PREFIX "/verstage");
Aaron Durbin17200ad2015-05-01 16:48:54 -0500100
Aaron Durbince2c50d2015-05-13 13:33:27 -0500101 printk(BIOS_DEBUG, "VBOOT: Loading verstage.\n");
102
Aaron Durbin17200ad2015-05-01 16:48:54 -0500103 /* load verstage from RO */
Aaron Durbin37a5d152015-09-17 16:09:30 -0500104 if (cbfs_boot_locate(&file, prog_name(&verstage), NULL))
105 die("failed to load verstage");
106
107 cbfs_file_data(prog_rdev(&verstage), &file);
108
109 if (cbfs_prog_stage_load(&verstage))
Aaron Durbin17200ad2015-05-01 16:48:54 -0500110 die("failed to load verstage");
111
112 /* verify and select a slot */
113 prog_run(&verstage);
114
115 /* This is not actually possible to hit this condition at
116 * runtime, but this provides a hint to the compiler for dead
117 * code elimination below. */
118 if (!IS_ENABLED(CONFIG_RETURN_FROM_VERSTAGE))
Aaron Durbin6d720f32015-12-08 17:00:23 -0600119 return;
120
121 car_set_var(vboot_executed, 1);
Aaron Durbin17200ad2015-05-01 16:48:54 -0500122 }
123
Aaron Durbinb5933662015-10-07 16:03:41 -0500124 /*
125 * Fill in vboot cbmem objects before moving to ramstage so all
126 * downstream users have access to vboot results. This path only
127 * applies to platforms employing VBOOT_DYNAMIC_WORK_BUFFER because
128 * cbmem comes online prior to vboot verification taking place. For
129 * other platforms the vboot cbmem objects are initialized when
130 * cbmem comes online.
131 */
132 if (ENV_ROMSTAGE && IS_ENABLED(CONFIG_VBOOT_DYNAMIC_WORK_BUFFER)) {
133 vb2_store_selected_region();
Aaron Durbin17200ad2015-05-01 16:48:54 -0500134 vboot_fill_handoff();
Aaron Durbinb5933662015-10-07 16:03:41 -0500135 }
Aaron Durbin17200ad2015-05-01 16:48:54 -0500136}
137
Aaron Durbin6d720f32015-12-08 17:00:23 -0600138static int vboot_locate(struct cbfs_props *props)
Aaron Durbin17200ad2015-05-01 16:48:54 -0500139{
Aaron Durbin6d720f32015-12-08 17:00:23 -0600140 struct region selected_region;
Aaron Durbin899d13d2015-05-15 23:39:23 -0500141
Aaron Durbin6d720f32015-12-08 17:00:23 -0600142 /* Don't honor vboot results until the vboot logic has run. */
Furquan Shaikha6c5ddd2016-07-22 06:59:40 -0700143 if (!vb2_logic_executed())
Aaron Durbinb6981c02015-05-15 15:57:51 -0500144 return -1;
Aaron Durbin17200ad2015-05-01 16:48:54 -0500145
Aaron Durbin6d720f32015-12-08 17:00:23 -0600146 if (vb2_get_selected_region(&selected_region))
Aaron Durbin4e50cdd2015-05-15 23:25:46 -0500147 return -1;
Aaron Durbinb6981c02015-05-15 15:57:51 -0500148
Aaron Durbin6d720f32015-12-08 17:00:23 -0600149 props->offset = region_offset(&selected_region);
150 props->size = region_sz(&selected_region);
Aaron Durbin17200ad2015-05-01 16:48:54 -0500151
Aaron Durbinb6981c02015-05-15 15:57:51 -0500152 return 0;
Aaron Durbin17200ad2015-05-01 16:48:54 -0500153}
154
Aaron Durbin6d720f32015-12-08 17:00:23 -0600155const struct cbfs_locator vboot_locator = {
Aaron Durbin17200ad2015-05-01 16:48:54 -0500156 .name = "VBOOT",
Aaron Durbin6d720f32015-12-08 17:00:23 -0600157 .prepare = vboot_prepare,
Aaron Durbin899d13d2015-05-15 23:39:23 -0500158 .locate = vboot_locate,
Aaron Durbin17200ad2015-05-01 16:48:54 -0500159};