blob: 241ba8c21ff50d2112625d46f26af59411989ea0 [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>
Aaron Durbind0084132016-11-29 15:52:08 -060012#include <romstage_handoff.h>
13#include <stage_cache.h>
Subrata Banik2847e1e2019-02-25 20:31:22 +053014#include <timestamp.h>
Wim Vervoorn1058dd82019-11-01 10:22:22 +010015#include <security/vboot/vboot_common.h>
Aaron Durbin7f8afe02016-03-18 12:21:23 -050016
17static inline void stack_push(struct postcar_frame *pcf, uint32_t val)
18{
19 uint32_t *ptr;
20
21 pcf->stack -= sizeof(val);
22 ptr = (void *)pcf->stack;
23 *ptr = val;
24}
25
Kyösti Mälkki029cebc2016-12-02 19:47:07 +020026static void postcar_frame_prepare(struct postcar_frame *pcf)
27{
Aaron Durbine1bf0652020-05-28 21:34:43 -060028 var_mtrr_context_init(&pcf->ctx, pcf);
Kyösti Mälkki029cebc2016-12-02 19:47:07 +020029}
30
Aaron Durbin7f8afe02016-03-18 12:21:23 -050031int postcar_frame_init(struct postcar_frame *pcf, size_t stack_size)
32{
33 void *stack;
Aaron Durbin7f8afe02016-03-18 12:21:23 -050034
Kyösti Mälkki6e2d0c12019-06-28 10:08:51 +030035 /*
36 * Use default postcar stack size of 4 KiB. This value should
37 * not be decreased, because if mainboards use vboot, 1 KiB will
38 * not be enough anymore.
39 */
40
41 if (stack_size == 0)
42 stack_size = 4 * KiB;
43
Aaron Durbin7f8afe02016-03-18 12:21:23 -050044 stack = cbmem_add(CBMEM_ID_ROMSTAGE_RAM_STACK, stack_size);
45 if (stack == NULL) {
46 printk(BIOS_ERR, "Couldn't add %zd byte stack in cbmem.\n",
47 stack_size);
48 return -1;
49 }
50
Kyösti Mälkki029cebc2016-12-02 19:47:07 +020051 postcar_frame_prepare(pcf);
Aaron Durbin7f8afe02016-03-18 12:21:23 -050052 pcf->stack = (uintptr_t)stack;
53 pcf->stack += stack_size;
Aaron Durbin7f8afe02016-03-18 12:21:23 -050054 return 0;
55}
56
Aaron Durbine1bf0652020-05-28 21:34:43 -060057static void postcar_var_mtrr_set(const struct var_mtrr_context *ctx,
58 uintptr_t addr, size_t size,
59 msr_t base, msr_t mask)
60{
61 struct postcar_frame *pcf = ctx->arg;
62
63 printk(BIOS_DEBUG, "MTRR Range: Start=%lx End=%lx (Size %zx)\n",
64 addr, addr + size, size);
65
66 stack_push(pcf, mask.hi);
67 stack_push(pcf, mask.lo);
68 stack_push(pcf, base.hi);
69 stack_push(pcf, base.lo);
70}
71
Aaron Durbin7f8afe02016-03-18 12:21:23 -050072void postcar_frame_add_mtrr(struct postcar_frame *pcf,
73 uintptr_t addr, size_t size, int type)
74{
Aaron Durbine1bf0652020-05-28 21:34:43 -060075 var_mtrr_set_with_cb(&pcf->ctx, addr, size, type, postcar_var_mtrr_set);
Aaron Durbin7f8afe02016-03-18 12:21:23 -050076}
77
Nico Huber36ec3e92018-05-27 14:32:27 +020078void postcar_frame_add_romcache(struct postcar_frame *pcf, int type)
79{
Julius Wernercd49cce2019-03-05 16:53:33 -080080 if (!CONFIG(BOOT_DEVICE_MEMORY_MAPPED))
Nico Huber36ec3e92018-05-27 14:32:27 +020081 return;
82 postcar_frame_add_mtrr(pcf, CACHE_ROM_BASE, CACHE_ROM_SIZE, type);
83}
84
Aaron Durbine8936742020-04-29 14:20:05 -060085static void postcar_frame_common_mtrrs(struct postcar_frame *pcf)
Kyösti Mälkki544878b2019-08-09 11:41:15 +030086{
87 if (pcf->skip_common_mtrr)
88 return;
89
Kyösti Mälkki544878b2019-08-09 11:41:15 +030090 /* Cache the ROM as WP just below 4GiB. */
91 postcar_frame_add_romcache(pcf, MTRR_TYPE_WRPROT);
92}
93
Kyösti Mälkkicd7a70f2019-08-17 20:51:08 +030094/* prepare_and_run_postcar() determines the stack to use after
95 * cache-as-ram is torn down as well as the MTRR settings to use. */
96void prepare_and_run_postcar(struct postcar_frame *pcf)
97{
98 if (postcar_frame_init(pcf, 0))
99 die("Unable to initialize postcar frame.\n");
100
101 fill_postcar_frame(pcf);
102
103 postcar_frame_common_mtrrs(pcf);
104
105 run_postcar_phase(pcf);
106 /* We do not return here. */
107}
108
Aaron Durbindf2bfb92019-08-27 20:22:40 -0600109static void postcar_commit_mtrrs(struct postcar_frame *pcf)
Rizwan Qureshib1b44d32016-08-26 21:08:50 +0530110{
111 /*
112 * Place the number of used variable MTRRs on stack then max number
113 * of variable MTRRs supported in the system.
114 */
Aaron Durbine1bf0652020-05-28 21:34:43 -0600115 stack_push(pcf, pcf->ctx.used_var_mtrrs);
116 stack_push(pcf, pcf->ctx.max_var_mtrrs);
Rizwan Qureshib1b44d32016-08-26 21:08:50 +0530117}
118
Kyösti Mälkkia7421fb2017-09-05 22:43:05 +0300119static void finalize_load(uintptr_t *stack_top_ptr, uintptr_t stack_top)
120{
121 *stack_top_ptr = stack_top;
122 /*
123 * Signal to rest of system that another update was made to the
124 * postcar program prior to running it.
125 */
126 prog_segment_loaded((uintptr_t)stack_top_ptr, sizeof(uintptr_t),
127 SEG_FINAL);
128}
129
Aaron Durbind0084132016-11-29 15:52:08 -0600130static void load_postcar_cbfs(struct prog *prog, struct postcar_frame *pcf)
Aaron Durbin7f8afe02016-03-18 12:21:23 -0500131{
Aaron Durbin7f8afe02016-03-18 12:21:23 -0500132 struct rmod_stage_load rsl = {
133 .cbmem_id = CBMEM_ID_AFTER_CAR,
Aaron Durbind0084132016-11-29 15:52:08 -0600134 .prog = prog,
Aaron Durbin7f8afe02016-03-18 12:21:23 -0500135 };
136
Wim Vervoorn1058dd82019-11-01 10:22:22 +0100137 vboot_run_logic();
138
Aaron Durbind0084132016-11-29 15:52:08 -0600139 if (prog_locate(prog))
Keith Short70064582019-05-06 16:12:57 -0600140 die_with_post_code(POST_INVALID_ROM,
141 "Failed to locate after CAR program.\n");
Aaron Durbin7f8afe02016-03-18 12:21:23 -0500142 if (rmodule_stage_load(&rsl))
Keith Short70064582019-05-06 16:12:57 -0600143 die_with_post_code(POST_INVALID_ROM,
144 "Failed to load after CAR program.\n");
Aaron Durbin7f8afe02016-03-18 12:21:23 -0500145
146 /* Set the stack pointer within parameters of the program loaded. */
147 if (rsl.params == NULL)
Keith Short70064582019-05-06 16:12:57 -0600148 die_with_post_code(POST_INVALID_ROM,
149 "No parameters found in after CAR program.\n");
Aaron Durbin7f8afe02016-03-18 12:21:23 -0500150
Kyösti Mälkkia7421fb2017-09-05 22:43:05 +0300151 finalize_load(rsl.params, pcf->stack);
Aaron Durbindd95e002016-03-31 13:36:33 -0500152
Subrata Banik90f750b2019-06-11 17:52:06 +0530153 stage_cache_add(STAGE_POSTCAR, prog);
Aaron Durbind0084132016-11-29 15:52:08 -0600154}
155
Subrata Banik8edc6dc2019-08-22 11:30:52 +0530156/*
157 * Cache the TSEG region at the top of ram. This region is
158 * not restricted to SMM mode until SMM has been relocated.
159 * By setting the region to cacheable it provides faster access
160 * when relocating the SMM handler as well as using the TSEG
161 * region for other purposes.
162 */
163void postcar_enable_tseg_cache(struct postcar_frame *pcf)
164{
165 uintptr_t smm_base;
166 size_t smm_size;
167
168 smm_region(&smm_base, &smm_size);
169 postcar_frame_add_mtrr(pcf, smm_base, smm_size,
170 MTRR_TYPE_WRBACK);
171}
172
Kyösti Mälkki4f14cd82019-12-18 19:40:48 +0200173static void postcar_cache_invalid(void)
174{
175 printk(BIOS_ERR, "postcar cache invalid.\n");
176 board_reset();
177}
178
Aaron Durbind0084132016-11-29 15:52:08 -0600179void run_postcar_phase(struct postcar_frame *pcf)
180{
181 struct prog prog =
Philipp Deppenwiese01797b12018-11-08 10:39:39 +0100182 PROG_INIT(PROG_POSTCAR, CONFIG_CBFS_PREFIX "/postcar");
Aaron Durbind0084132016-11-29 15:52:08 -0600183
184 postcar_commit_mtrrs(pcf);
185
Julius Wernercd49cce2019-03-05 16:53:33 -0800186 if (!CONFIG(NO_STAGE_CACHE) &&
Kyösti Mälkkia7421fb2017-09-05 22:43:05 +0300187 romstage_handoff_is_resume()) {
Aaron Durbind0084132016-11-29 15:52:08 -0600188 stage_cache_load_stage(STAGE_POSTCAR, &prog);
Aaron Durbinc546c762018-04-23 14:55:09 -0600189 /* This is here to allow platforms to pass different stack
190 parameters between S3 resume and normal boot. On the
191 platforms where the values are the same it's a nop. */
Kyösti Mälkkia7421fb2017-09-05 22:43:05 +0300192 finalize_load(prog.arg, pcf->stack);
Kyösti Mälkki4f14cd82019-12-18 19:40:48 +0200193
194 if (prog_entry(&prog) == NULL)
195 postcar_cache_invalid();
Kyösti Mälkkia7421fb2017-09-05 22:43:05 +0300196 } else
Aaron Durbind0084132016-11-29 15:52:08 -0600197 load_postcar_cbfs(&prog, pcf);
198
Subrata Banik2847e1e2019-02-25 20:31:22 +0530199 /* As postcar exist, it's end of romstage here */
200 timestamp_add_now(TS_END_ROMSTAGE);
201
Kyösti Mälkki45ddb432019-11-02 14:12:18 +0200202 console_time_report();
203
Arthur Heymans5331a7c2019-10-23 17:07:15 +0200204 prog_set_arg(&prog, cbmem_top());
205
Aaron Durbin7f8afe02016-03-18 12:21:23 -0500206 prog_run(&prog);
207}