blob: f8442d5d7276904de5784f2fba6dbfcd3d8b3f8a [file] [log] [blame]
Patrick Georgi11f00792020-03-04 15:10:45 +01001/* SPDX-License-Identifier: GPL-2.0-only */
Aaron Durbin7f8afe02016-03-18 12:21:23 -05002
Kyösti Mälkkia963acd2019-08-16 20:34:25 +03003#include <arch/romstage.h>
Aaron Durbin7f8afe02016-03-18 12:21:23 -05004#include <cbmem.h>
5#include <console/console.h>
6#include <cpu/x86/msr.h>
7#include <cpu/x86/mtrr.h>
Subrata Banik8edc6dc2019-08-22 11:30:52 +05308#include <cpu/x86/smm.h>
Aaron Durbin7f8afe02016-03-18 12:21:23 -05009#include <program_loading.h>
Kyösti Mälkki4f14cd82019-12-18 19:40:48 +020010#include <reset.h>
Aaron Durbin7f8afe02016-03-18 12:21:23 -050011#include <rmodule.h>
Arthur Heymans3134a812019-11-25 12:20:01 +010012#include <romstage_handoff.h>
Elyes Haouasae1ca822022-10-07 10:02:38 +020013#include <security/vboot/vboot_common.h>
Aaron Durbind0084132016-11-29 15:52:08 -060014#include <stage_cache.h>
Subrata Banik2847e1e2019-02-25 20:31:22 +053015#include <timestamp.h>
Elyes Haouasae1ca822022-10-07 10:02:38 +020016#include <types.h>
Aaron Durbin7f8afe02016-03-18 12:21:23 -050017
Arthur Heymans46b409d2021-05-14 13:19:43 +020018static size_t var_mtrr_ctx_size(void)
Aaron Durbin7f8afe02016-03-18 12:21:23 -050019{
Arthur Heymans46b409d2021-05-14 13:19:43 +020020 int mtrr_count = get_var_mtrr_count();
21 return sizeof(struct var_mtrr_context) + mtrr_count * 2 * sizeof(msr_t);
Aaron Durbin7f8afe02016-03-18 12:21:23 -050022}
23
Elyes Haouas9523e3b2022-11-08 14:38:41 +010024static enum cb_err postcar_frame_init(struct postcar_frame *pcf)
Kyösti Mälkki029cebc2016-12-02 19:47:07 +020025{
Arthur Heymans876a1b42022-02-15 11:06:10 +010026 memset(pcf, 0, sizeof(*pcf));
27
Arthur Heymans46b409d2021-05-14 13:19:43 +020028 struct var_mtrr_context *ctx;
Kyösti Mälkki029cebc2016-12-02 19:47:07 +020029
Arthur Heymans46b409d2021-05-14 13:19:43 +020030 ctx = cbmem_add(CBMEM_ID_ROMSTAGE_RAM_STACK, var_mtrr_ctx_size());
31 if (ctx == NULL) {
32 printk(BIOS_ERR, "Couldn't add var_mtrr_ctx setup in cbmem.\n");
Elyes Haouas9523e3b2022-11-08 14:38:41 +010033 return CB_ERR;
Aaron Durbin7f8afe02016-03-18 12:21:23 -050034 }
35
Arthur Heymans46b409d2021-05-14 13:19:43 +020036 pcf->mtrr = ctx;
37 var_mtrr_context_init(pcf->mtrr);
38
Elyes Haouas9523e3b2022-11-08 14:38:41 +010039 return CB_SUCCESS;
Aaron Durbin7f8afe02016-03-18 12:21:23 -050040}
41
42void postcar_frame_add_mtrr(struct postcar_frame *pcf,
43 uintptr_t addr, size_t size, int type)
44{
Arthur Heymans46b409d2021-05-14 13:19:43 +020045 var_mtrr_set(pcf->mtrr, addr, size, type);
Aaron Durbin7f8afe02016-03-18 12:21:23 -050046}
47
Nico Huber36ec3e92018-05-27 14:32:27 +020048void postcar_frame_add_romcache(struct postcar_frame *pcf, int type)
49{
Julius Wernercd49cce2019-03-05 16:53:33 -080050 if (!CONFIG(BOOT_DEVICE_MEMORY_MAPPED))
Nico Huber36ec3e92018-05-27 14:32:27 +020051 return;
52 postcar_frame_add_mtrr(pcf, CACHE_ROM_BASE, CACHE_ROM_SIZE, type);
53}
54
Aaron Durbine8936742020-04-29 14:20:05 -060055static void postcar_frame_common_mtrrs(struct postcar_frame *pcf)
Kyösti Mälkki544878b2019-08-09 11:41:15 +030056{
57 if (pcf->skip_common_mtrr)
58 return;
59
Kyösti Mälkki544878b2019-08-09 11:41:15 +030060 /* Cache the ROM as WP just below 4GiB. */
61 postcar_frame_add_romcache(pcf, MTRR_TYPE_WRPROT);
62}
63
Arthur Heymansba00d102022-02-15 11:04:15 +010064static void run_postcar_phase(struct postcar_frame *pcf);
65
Kyösti Mälkkicd7a70f2019-08-17 20:51:08 +030066/* prepare_and_run_postcar() determines the stack to use after
67 * cache-as-ram is torn down as well as the MTRR settings to use. */
Arthur Heymansefd27202022-07-13 07:20:47 +020068void __noreturn prepare_and_run_postcar(void)
Kyösti Mälkkicd7a70f2019-08-17 20:51:08 +030069{
Arthur Heymans876a1b42022-02-15 11:06:10 +010070 struct postcar_frame pcf;
71
72 if (postcar_frame_init(&pcf))
Kyösti Mälkkicd7a70f2019-08-17 20:51:08 +030073 die("Unable to initialize postcar frame.\n");
74
Arthur Heymans876a1b42022-02-15 11:06:10 +010075 fill_postcar_frame(&pcf);
Kyösti Mälkkicd7a70f2019-08-17 20:51:08 +030076
Arthur Heymans876a1b42022-02-15 11:06:10 +010077 postcar_frame_common_mtrrs(&pcf);
Kyösti Mälkkicd7a70f2019-08-17 20:51:08 +030078
Arthur Heymans876a1b42022-02-15 11:06:10 +010079 run_postcar_phase(&pcf);
Kyösti Mälkkicd7a70f2019-08-17 20:51:08 +030080 /* We do not return here. */
Arthur Heymansefd27202022-07-13 07:20:47 +020081 die("Failed to load postcar\n!");
Kyösti Mälkkicd7a70f2019-08-17 20:51:08 +030082}
83
Arthur Heymans46b409d2021-05-14 13:19:43 +020084static void finalize_load(uintptr_t *reloc_params, uintptr_t mtrr_frame_ptr)
Rizwan Qureshib1b44d32016-08-26 21:08:50 +053085{
Arthur Heymans46b409d2021-05-14 13:19:43 +020086 *reloc_params = mtrr_frame_ptr;
Kyösti Mälkkia7421fb2017-09-05 22:43:05 +030087 /*
88 * Signal to rest of system that another update was made to the
89 * postcar program prior to running it.
90 */
Arthur Heymans46b409d2021-05-14 13:19:43 +020091 prog_segment_loaded((uintptr_t)reloc_params, sizeof(uintptr_t), SEG_FINAL);
92 prog_segment_loaded((uintptr_t)mtrr_frame_ptr, var_mtrr_ctx_size(), SEG_FINAL);
Kyösti Mälkkia7421fb2017-09-05 22:43:05 +030093}
94
Aaron Durbind0084132016-11-29 15:52:08 -060095static void load_postcar_cbfs(struct prog *prog, struct postcar_frame *pcf)
Aaron Durbin7f8afe02016-03-18 12:21:23 -050096{
Aaron Durbin7f8afe02016-03-18 12:21:23 -050097 struct rmod_stage_load rsl = {
98 .cbmem_id = CBMEM_ID_AFTER_CAR,
Aaron Durbind0084132016-11-29 15:52:08 -060099 .prog = prog,
Aaron Durbin7f8afe02016-03-18 12:21:23 -0500100 };
101
Wim Vervoorn1058dd82019-11-01 10:22:22 +0100102 vboot_run_logic();
103
Aaron Durbin7f8afe02016-03-18 12:21:23 -0500104 if (rmodule_stage_load(&rsl))
lilacious40cb3fe2023-06-21 23:24:14 +0200105 die_with_post_code(POSTCODE_INVALID_ROM,
Keith Short70064582019-05-06 16:12:57 -0600106 "Failed to load after CAR program.\n");
Aaron Durbin7f8afe02016-03-18 12:21:23 -0500107
108 /* Set the stack pointer within parameters of the program loaded. */
109 if (rsl.params == NULL)
lilacious40cb3fe2023-06-21 23:24:14 +0200110 die_with_post_code(POSTCODE_INVALID_ROM,
Keith Short70064582019-05-06 16:12:57 -0600111 "No parameters found in after CAR program.\n");
Aaron Durbin7f8afe02016-03-18 12:21:23 -0500112
Arthur Heymans46b409d2021-05-14 13:19:43 +0200113 finalize_load(rsl.params, (uintptr_t)pcf->mtrr);
Aaron Durbindd95e002016-03-31 13:36:33 -0500114
Subrata Banik90f750b2019-06-11 17:52:06 +0530115 stage_cache_add(STAGE_POSTCAR, prog);
Aaron Durbind0084132016-11-29 15:52:08 -0600116}
117
Subrata Banik8edc6dc2019-08-22 11:30:52 +0530118/*
119 * Cache the TSEG region at the top of ram. This region is
120 * not restricted to SMM mode until SMM has been relocated.
121 * By setting the region to cacheable it provides faster access
122 * when relocating the SMM handler as well as using the TSEG
123 * region for other purposes.
124 */
125void postcar_enable_tseg_cache(struct postcar_frame *pcf)
126{
127 uintptr_t smm_base;
128 size_t smm_size;
129
130 smm_region(&smm_base, &smm_size);
131 postcar_frame_add_mtrr(pcf, smm_base, smm_size,
132 MTRR_TYPE_WRBACK);
133}
134
Kyösti Mälkki4f14cd82019-12-18 19:40:48 +0200135static void postcar_cache_invalid(void)
136{
137 printk(BIOS_ERR, "postcar cache invalid.\n");
138 board_reset();
139}
140
Arthur Heymans3134a812019-11-25 12:20:01 +0100141/*
142 * POSTCAR will call invd so don't make assumptions on cbmem
143 * and external stage cache being UC.
144 */
145static void postcar_flush_cache(void)
146{
147 uintptr_t cbmem_base;
148 size_t cbmem_size;
149 uintptr_t stage_cache_base;
150 size_t stage_cache_size;
151
152 cbmem_get_region((void **)&cbmem_base, &cbmem_size);
153 prog_segment_loaded(cbmem_base, cbmem_size, SEG_FINAL);
154 if (CONFIG(TSEG_STAGE_CACHE) && !romstage_handoff_is_resume()) {
155 stage_cache_external_region((void **)&stage_cache_base, &stage_cache_size);
156 prog_segment_loaded(stage_cache_base, stage_cache_size, SEG_FINAL);
157 }
158}
159
Arthur Heymansba00d102022-02-15 11:04:15 +0100160static void run_postcar_phase(struct postcar_frame *pcf)
Aaron Durbind0084132016-11-29 15:52:08 -0600161{
162 struct prog prog =
Philipp Deppenwiese01797b12018-11-08 10:39:39 +0100163 PROG_INIT(PROG_POSTCAR, CONFIG_CBFS_PREFIX "/postcar");
Aaron Durbind0084132016-11-29 15:52:08 -0600164
Kyösti Mälkkie0165fb2021-01-09 13:30:57 +0200165 if (resume_from_stage_cache()) {
Aaron Durbind0084132016-11-29 15:52:08 -0600166 stage_cache_load_stage(STAGE_POSTCAR, &prog);
Aaron Durbinc546c762018-04-23 14:55:09 -0600167 /* This is here to allow platforms to pass different stack
168 parameters between S3 resume and normal boot. On the
169 platforms where the values are the same it's a nop. */
Arthur Heymans46b409d2021-05-14 13:19:43 +0200170 finalize_load(prog.arg, (uintptr_t)pcf->mtrr);
Kyösti Mälkki4f14cd82019-12-18 19:40:48 +0200171
172 if (prog_entry(&prog) == NULL)
173 postcar_cache_invalid();
Kyösti Mälkkia7421fb2017-09-05 22:43:05 +0300174 } else
Aaron Durbind0084132016-11-29 15:52:08 -0600175 load_postcar_cbfs(&prog, pcf);
176
Subrata Banik2847e1e2019-02-25 20:31:22 +0530177 /* As postcar exist, it's end of romstage here */
Jakub Czapigaad6157e2022-02-15 11:50:31 +0100178 timestamp_add_now(TS_ROMSTAGE_END);
Subrata Banik2847e1e2019-02-25 20:31:22 +0530179
Kyösti Mälkki45ddb432019-11-02 14:12:18 +0200180 console_time_report();
181
Arthur Heymans3134a812019-11-25 12:20:01 +0100182 postcar_flush_cache();
183
Arthur Heymans5331a7c2019-10-23 17:07:15 +0200184 prog_set_arg(&prog, cbmem_top());
185
Aaron Durbin7f8afe02016-03-18 12:21:23 -0500186 prog_run(&prog);
187}