tree: drop last paragraph of GPL copyright header
[coreboot.git] / src / vendorcode / google / chromeos / vboot2 / vboot_loader.c
blobb5570dd7cae45c583f82737c29f95df28f2c67bd
1 /*
2 * This file is part of the coreboot project.
4 * Copyright 2015 Google, Inc.
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.
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.
16 #include <assets.h>
17 #include <cbfs.h>
18 #include <cbmem.h>
19 #include <console/console.h>
20 #include <rmodule.h>
21 #include <rules.h>
22 #include <string.h>
23 #include "misc.h"
24 #include "../vboot_handoff.h"
25 #include "../symbols.h"
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. */
31 static int verification_should_run(void)
33 if (ENV_VERSTAGE && IS_ENABLED(CONFIG_SEPARATE_VERSTAGE))
34 return 1;
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;
45 return 0;
48 static int verstage_should_load(void)
50 if (!IS_ENABLED(CONFIG_SEPARATE_VERSTAGE))
51 return 0;
53 if (ENV_ROMSTAGE && IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE))
54 return 1;
56 if (ENV_BOOTBLOCK && IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK))
57 return 1;
59 return 0;
62 static int vboot_active(struct asset *asset)
64 int run_verification;
66 run_verification = verification_should_run();
68 if (run_verification) {
69 verstage_main();
70 } else if (verstage_should_load()) {
71 struct cbfsf file;
72 struct prog verstage =
73 PROG_INIT(ASSET_VERSTAGE,
74 CONFIG_CBFS_PREFIX "/verstage");
76 printk(BIOS_DEBUG, "VBOOT: Loading verstage.\n");
78 /* load verstage from RO */
79 if (cbfs_boot_locate(&file, prog_name(&verstage), NULL))
80 die("failed to load verstage");
82 cbfs_file_data(prog_rdev(&verstage), &file);
84 if (cbfs_prog_stage_load(&verstage))
85 die("failed to load verstage");
87 /* verify and select a slot */
88 prog_run(&verstage);
90 /* This is not actually possible to hit this condition at
91 * runtime, but this provides a hint to the compiler for dead
92 * code elimination below. */
93 if (!IS_ENABLED(CONFIG_RETURN_FROM_VERSTAGE))
94 return 0;
98 * Fill in vboot cbmem objects before moving to ramstage so all
99 * downstream users have access to vboot results. This path only
100 * applies to platforms employing VBOOT_DYNAMIC_WORK_BUFFER because
101 * cbmem comes online prior to vboot verification taking place. For
102 * other platforms the vboot cbmem objects are initialized when
103 * cbmem comes online.
105 if (ENV_ROMSTAGE && IS_ENABLED(CONFIG_VBOOT_DYNAMIC_WORK_BUFFER)) {
106 vb2_store_selected_region();
107 vboot_fill_handoff();
110 return vboot_is_slot_selected();
113 static int vboot_locate_by_components(const struct region_device *fw_main,
114 struct asset *asset)
116 struct vboot_components *fw_info;
117 size_t metadata_sz;
118 size_t offset;
119 size_t size;
120 struct region_device *fw = asset_rdev(asset);
121 int fw_index = 0;
123 if (asset_type(asset) == ASSET_ROMSTAGE)
124 fw_index = CONFIG_VBOOT_ROMSTAGE_INDEX;
125 else if (asset_type(asset) == ASSET_RAMSTAGE)
126 fw_index = CONFIG_VBOOT_RAMSTAGE_INDEX;
127 else if (asset_type(asset) == ASSET_PAYLOAD)
128 fw_index = CONFIG_VBOOT_BOOT_LOADER_INDEX;
129 else if (asset_type(asset) == ASSET_REFCODE)
130 fw_index = CONFIG_VBOOT_REFCODE_INDEX;
131 else if (asset_type(asset) == ASSET_BL31)
132 fw_index = CONFIG_VBOOT_BL31_INDEX;
133 else
134 die("Invalid program type for vboot.");
136 metadata_sz = sizeof(*fw_info);
137 metadata_sz += MAX_PARSED_FW_COMPONENTS * sizeof(fw_info->entries[0]);
139 fw_info = rdev_mmap(fw_main, 0, metadata_sz);
141 if (fw_info == NULL) {
142 printk(BIOS_INFO, "No component metadata.\n");
143 return -1;
146 if (fw_index >= fw_info->num_components) {
147 printk(BIOS_INFO, "invalid index: %d\n", fw_index);
148 rdev_munmap(fw_main, fw_info);
149 return -1;
152 offset = fw_info->entries[fw_index].offset;
153 size = fw_info->entries[fw_index].size;
154 rdev_munmap(fw_main, fw_info);
156 if (rdev_chain(fw, fw_main, offset, size)) {
157 printk(BIOS_INFO, "invalid offset or size\n");
158 return -1;
161 return 0;
164 static int vboot_locate_by_multi_cbfs(const struct region_device *fw_main,
165 struct asset *asset)
167 struct cbfsf file;
169 if (cbfs_locate(&file, fw_main, asset_name(asset), NULL))
170 return -1;
172 cbfs_file_data(asset_rdev(asset), &file);
174 return 0;
177 static int vboot_asset_locate(const struct region_device *fw_main,
178 struct asset *asset)
180 if (IS_ENABLED(CONFIG_MULTIPLE_CBFS_INSTANCES))
181 return vboot_locate_by_multi_cbfs(fw_main, asset);
182 else
183 return vboot_locate_by_components(fw_main, asset);
186 /* This function is only called when vboot_active() returns 1. That
187 * means we are taking vboot paths. */
188 static int vboot_locate(struct asset *asset)
190 struct region_device fw_main;
192 /* Code size optimization. We'd never actually get called under the
193 * followin cirumstances because verstage was loaded and ran -- never
194 * returning. */
195 if (verstage_should_load() && !IS_ENABLED(CONFIG_RETURN_FROM_VERSTAGE))
196 return 0;
198 if (vb2_get_selected_region(&fw_main))
199 die("failed to reference selected region\n");
201 return vboot_asset_locate(&fw_main, asset);
204 const struct asset_provider vboot_provider = {
205 .name = "VBOOT",
206 .is_active = vboot_active,
207 .locate = vboot_locate,