1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <arch/romstage.h>
5 #include <console/console.h>
6 #include <cpu/x86/msr.h>
7 #include <cpu/x86/mtrr.h>
8 #include <cpu/x86/smm.h>
9 #include <program_loading.h>
12 #include <stage_cache.h>
13 #include <timestamp.h>
14 #include <security/vboot/vboot_common.h>
16 static inline void stack_push(struct postcar_frame
*pcf
, uint32_t val
)
20 pcf
->stack
-= sizeof(val
);
21 ptr
= (void *)pcf
->stack
;
25 static void postcar_frame_prepare(struct postcar_frame
*pcf
)
27 var_mtrr_context_init(&pcf
->ctx
, pcf
);
30 int postcar_frame_init(struct postcar_frame
*pcf
, size_t stack_size
)
35 * Use default postcar stack size of 4 KiB. This value should
36 * not be decreased, because if mainboards use vboot, 1 KiB will
37 * not be enough anymore.
43 stack
= cbmem_add(CBMEM_ID_ROMSTAGE_RAM_STACK
, stack_size
);
45 printk(BIOS_ERR
, "Couldn't add %zd byte stack in cbmem.\n",
50 postcar_frame_prepare(pcf
);
51 pcf
->stack
= (uintptr_t)stack
;
52 pcf
->stack
+= stack_size
;
56 static void postcar_var_mtrr_set(const struct var_mtrr_context
*ctx
,
57 uintptr_t addr
, size_t size
,
58 msr_t base
, msr_t mask
)
60 struct postcar_frame
*pcf
= ctx
->arg
;
62 printk(BIOS_DEBUG
, "MTRR Range: Start=%lx End=%lx (Size %zx)\n",
63 addr
, addr
+ size
, size
);
65 stack_push(pcf
, mask
.hi
);
66 stack_push(pcf
, mask
.lo
);
67 stack_push(pcf
, base
.hi
);
68 stack_push(pcf
, base
.lo
);
71 void postcar_frame_add_mtrr(struct postcar_frame
*pcf
,
72 uintptr_t addr
, size_t size
, int type
)
74 var_mtrr_set_with_cb(&pcf
->ctx
, addr
, size
, type
, postcar_var_mtrr_set
);
77 void postcar_frame_add_romcache(struct postcar_frame
*pcf
, int type
)
79 if (!CONFIG(BOOT_DEVICE_MEMORY_MAPPED
))
81 postcar_frame_add_mtrr(pcf
, CACHE_ROM_BASE
, CACHE_ROM_SIZE
, type
);
84 static void postcar_frame_common_mtrrs(struct postcar_frame
*pcf
)
86 if (pcf
->skip_common_mtrr
)
89 /* Cache the ROM as WP just below 4GiB. */
90 postcar_frame_add_romcache(pcf
, MTRR_TYPE_WRPROT
);
93 /* prepare_and_run_postcar() determines the stack to use after
94 * cache-as-ram is torn down as well as the MTRR settings to use. */
95 void prepare_and_run_postcar(struct postcar_frame
*pcf
)
97 if (postcar_frame_init(pcf
, 0))
98 die("Unable to initialize postcar frame.\n");
100 fill_postcar_frame(pcf
);
102 postcar_frame_common_mtrrs(pcf
);
104 run_postcar_phase(pcf
);
105 /* We do not return here. */
108 static void postcar_commit_mtrrs(struct postcar_frame
*pcf
)
111 * Place the number of used variable MTRRs on stack then max number
112 * of variable MTRRs supported in the system.
114 stack_push(pcf
, pcf
->ctx
.used_var_mtrrs
);
115 stack_push(pcf
, pcf
->ctx
.max_var_mtrrs
);
118 static void finalize_load(uintptr_t *stack_top_ptr
, uintptr_t stack_top
)
120 *stack_top_ptr
= stack_top
;
122 * Signal to rest of system that another update was made to the
123 * postcar program prior to running it.
125 prog_segment_loaded((uintptr_t)stack_top_ptr
, sizeof(uintptr_t),
129 static void load_postcar_cbfs(struct prog
*prog
, struct postcar_frame
*pcf
)
131 struct rmod_stage_load rsl
= {
132 .cbmem_id
= CBMEM_ID_AFTER_CAR
,
138 if (rmodule_stage_load(&rsl
))
139 die_with_post_code(POST_INVALID_ROM
,
140 "Failed to load after CAR program.\n");
142 /* Set the stack pointer within parameters of the program loaded. */
143 if (rsl
.params
== NULL
)
144 die_with_post_code(POST_INVALID_ROM
,
145 "No parameters found in after CAR program.\n");
147 finalize_load(rsl
.params
, pcf
->stack
);
149 stage_cache_add(STAGE_POSTCAR
, prog
);
153 * Cache the TSEG region at the top of ram. This region is
154 * not restricted to SMM mode until SMM has been relocated.
155 * By setting the region to cacheable it provides faster access
156 * when relocating the SMM handler as well as using the TSEG
157 * region for other purposes.
159 void postcar_enable_tseg_cache(struct postcar_frame
*pcf
)
164 smm_region(&smm_base
, &smm_size
);
165 postcar_frame_add_mtrr(pcf
, smm_base
, smm_size
,
169 static void postcar_cache_invalid(void)
171 printk(BIOS_ERR
, "postcar cache invalid.\n");
175 void run_postcar_phase(struct postcar_frame
*pcf
)
178 PROG_INIT(PROG_POSTCAR
, CONFIG_CBFS_PREFIX
"/postcar");
180 postcar_commit_mtrrs(pcf
);
182 if (resume_from_stage_cache()) {
183 stage_cache_load_stage(STAGE_POSTCAR
, &prog
);
184 /* This is here to allow platforms to pass different stack
185 parameters between S3 resume and normal boot. On the
186 platforms where the values are the same it's a nop. */
187 finalize_load(prog
.arg
, pcf
->stack
);
189 if (prog_entry(&prog
) == NULL
)
190 postcar_cache_invalid();
192 load_postcar_cbfs(&prog
, pcf
);
194 /* As postcar exist, it's end of romstage here */
195 timestamp_add_now(TS_END_ROMSTAGE
);
197 console_time_report();
199 prog_set_arg(&prog
, cbmem_top());