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.
19 #include <console/console.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
))
36 if (!IS_ENABLED(CONFIG_SEPARATE_VERSTAGE
)) {
38 IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE
))
41 IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK
))
48 static int verstage_should_load(void)
50 if (!IS_ENABLED(CONFIG_SEPARATE_VERSTAGE
))
53 if (ENV_ROMSTAGE
&& IS_ENABLED(CONFIG_VBOOT_STARTS_IN_ROMSTAGE
))
56 if (ENV_BOOTBLOCK
&& IS_ENABLED(CONFIG_VBOOT_STARTS_IN_BOOTBLOCK
))
62 static int vboot_active(struct asset
*asset
)
66 run_verification
= verification_should_run();
68 if (run_verification
) {
70 } else if (verstage_should_load()) {
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 */
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
))
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
,
116 struct vboot_components
*fw_info
;
120 struct region_device
*fw
= asset_rdev(asset
);
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
;
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");
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
);
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");
164 static int vboot_locate_by_multi_cbfs(const struct region_device
*fw_main
,
169 if (cbfs_locate(&file
, fw_main
, asset_name(asset
), NULL
))
172 cbfs_file_data(asset_rdev(asset
), &file
);
177 static int vboot_asset_locate(const struct region_device
*fw_main
,
180 if (IS_ENABLED(CONFIG_MULTIPLE_CBFS_INSTANCES
))
181 return vboot_locate_by_multi_cbfs(fw_main
, asset
);
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
195 if (verstage_should_load() && !IS_ENABLED(CONFIG_RETURN_FROM_VERSTAGE
))
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
= {
206 .is_active
= vboot_active
,
207 .locate
= vboot_locate
,