blob: b1b2da0540b598b00d9786c8f2a1f2b793d94d01 [file] [log] [blame]
Aaron Durbin7f8afe02016-03-18 12:21:23 -05001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright 2016 Google Inc.
5 *
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.
9 *
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.
14 */
15
16#include <arch/cpu.h>
17#include <cbmem.h>
18#include <console/console.h>
Kyösti Mälkki140087f2016-12-06 14:00:05 +020019#include <cpu/cpu.h>
Aaron Durbin7f8afe02016-03-18 12:21:23 -050020#include <cpu/x86/msr.h>
21#include <cpu/x86/mtrr.h>
22#include <program_loading.h>
23#include <rmodule.h>
Aaron Durbind0084132016-11-29 15:52:08 -060024#include <romstage_handoff.h>
25#include <stage_cache.h>
Subrata Banik2847e1e2019-02-25 20:31:22 +053026#include <timestamp.h>
Aaron Durbin7f8afe02016-03-18 12:21:23 -050027
28static inline void stack_push(struct postcar_frame *pcf, uint32_t val)
29{
30 uint32_t *ptr;
31
32 pcf->stack -= sizeof(val);
33 ptr = (void *)pcf->stack;
34 *ptr = val;
35}
36
Kyösti Mälkki029cebc2016-12-02 19:47:07 +020037static void postcar_frame_prepare(struct postcar_frame *pcf)
38{
39 msr_t msr;
40 msr = rdmsr(MTRR_CAP_MSR);
41
42 pcf->upper_mask = (1 << (cpu_phys_address_size() - 32)) - 1;
Kyösti Mälkkia097fb82017-09-12 10:36:49 +030043 pcf->max_var_mtrrs = msr.lo & MTRR_CAP_VCNT;
44 pcf->num_var_mtrrs = 0;
Kyösti Mälkki029cebc2016-12-02 19:47:07 +020045}
46
Aaron Durbin7f8afe02016-03-18 12:21:23 -050047int postcar_frame_init(struct postcar_frame *pcf, size_t stack_size)
48{
49 void *stack;
Aaron Durbin7f8afe02016-03-18 12:21:23 -050050
Kyösti Mälkki6e2d0c12019-06-28 10:08:51 +030051 /*
52 * Use default postcar stack size of 4 KiB. This value should
53 * not be decreased, because if mainboards use vboot, 1 KiB will
54 * not be enough anymore.
55 */
56
57 if (stack_size == 0)
58 stack_size = 4 * KiB;
59
Aaron Durbin7f8afe02016-03-18 12:21:23 -050060 stack = cbmem_add(CBMEM_ID_ROMSTAGE_RAM_STACK, stack_size);
61 if (stack == NULL) {
62 printk(BIOS_ERR, "Couldn't add %zd byte stack in cbmem.\n",
63 stack_size);
64 return -1;
65 }
66
Kyösti Mälkki029cebc2016-12-02 19:47:07 +020067 postcar_frame_prepare(pcf);
Aaron Durbin7f8afe02016-03-18 12:21:23 -050068 pcf->stack = (uintptr_t)stack;
69 pcf->stack += stack_size;
Aaron Durbin7f8afe02016-03-18 12:21:23 -050070 return 0;
71}
72
73void postcar_frame_add_mtrr(struct postcar_frame *pcf,
74 uintptr_t addr, size_t size, int type)
75{
Rizwan Qureshie8c2e832016-09-07 20:18:17 +053076 /*
77 * Utilize additional MTRRs if the specified size is greater than the
78 * base address alignment.
79 */
80 while (size != 0) {
81 uint32_t addr_lsb;
82 uint32_t size_msb;
83 uint32_t mtrr_size;
Aaron Durbin7f8afe02016-03-18 12:21:23 -050084
Kyösti Mälkkia097fb82017-09-12 10:36:49 +030085 if (pcf->num_var_mtrrs >= pcf->max_var_mtrrs) {
Rizwan Qureshie8c2e832016-09-07 20:18:17 +053086 printk(BIOS_ERR, "No more variable MTRRs: %d\n",
Kyösti Mälkkia097fb82017-09-12 10:36:49 +030087 pcf->max_var_mtrrs);
Rizwan Qureshie8c2e832016-09-07 20:18:17 +053088 return;
89 }
90
91 addr_lsb = fls(addr);
92 size_msb = fms(size);
93
94 /* All MTRR entries need to have their base aligned to the mask
95 * size. The maximum size is calculated by a function of the
96 * min base bit set and maximum size bit set. */
97 if (addr_lsb > size_msb)
98 mtrr_size = 1 << size_msb;
99 else
100 mtrr_size = 1 << addr_lsb;
101
102 printk(BIOS_DEBUG, "MTRR Range: Start=%lx End=%lx (Size %x)\n",
103 addr, addr + mtrr_size, mtrr_size);
104
105 stack_push(pcf, pcf->upper_mask);
106 stack_push(pcf, ~(mtrr_size - 1) | MTRR_PHYS_MASK_VALID);
107 stack_push(pcf, 0);
108 stack_push(pcf, addr | type);
Kyösti Mälkkia097fb82017-09-12 10:36:49 +0300109 pcf->num_var_mtrrs++;
Rizwan Qureshie8c2e832016-09-07 20:18:17 +0530110
111 size -= mtrr_size;
112 addr += mtrr_size;
Aaron Durbin7f8afe02016-03-18 12:21:23 -0500113 }
Aaron Durbin7f8afe02016-03-18 12:21:23 -0500114}
115
Nico Huber36ec3e92018-05-27 14:32:27 +0200116void postcar_frame_add_romcache(struct postcar_frame *pcf, int type)
117{
Julius Wernercd49cce2019-03-05 16:53:33 -0800118 if (!CONFIG(BOOT_DEVICE_MEMORY_MAPPED))
Nico Huber36ec3e92018-05-27 14:32:27 +0200119 return;
120 postcar_frame_add_mtrr(pcf, CACHE_ROM_BASE, CACHE_ROM_SIZE, type);
121}
122
Kyösti Mälkki544878b2019-08-09 11:41:15 +0300123void postcar_frame_common_mtrrs(struct postcar_frame *pcf)
124{
125 if (pcf->skip_common_mtrr)
126 return;
127
128 /* Cache RAM as WB from 0 -> CACHE_TMP_RAMTOP. */
129 postcar_frame_add_mtrr(pcf, 0, CACHE_TMP_RAMTOP, MTRR_TYPE_WRBACK);
130
131 /* Cache the ROM as WP just below 4GiB. */
132 postcar_frame_add_romcache(pcf, MTRR_TYPE_WRPROT);
133}
134
Rizwan Qureshib1b44d32016-08-26 21:08:50 +0530135void *postcar_commit_mtrrs(struct postcar_frame *pcf)
136{
137 /*
138 * Place the number of used variable MTRRs on stack then max number
139 * of variable MTRRs supported in the system.
140 */
Kyösti Mälkkia097fb82017-09-12 10:36:49 +0300141 stack_push(pcf, pcf->num_var_mtrrs);
142 stack_push(pcf, pcf->max_var_mtrrs);
Rizwan Qureshib1b44d32016-08-26 21:08:50 +0530143 return (void *) pcf->stack;
144}
145
Kyösti Mälkkia7421fb2017-09-05 22:43:05 +0300146static void finalize_load(uintptr_t *stack_top_ptr, uintptr_t stack_top)
147{
148 *stack_top_ptr = stack_top;
149 /*
150 * Signal to rest of system that another update was made to the
151 * postcar program prior to running it.
152 */
153 prog_segment_loaded((uintptr_t)stack_top_ptr, sizeof(uintptr_t),
154 SEG_FINAL);
155}
156
Aaron Durbind0084132016-11-29 15:52:08 -0600157static void load_postcar_cbfs(struct prog *prog, struct postcar_frame *pcf)
Aaron Durbin7f8afe02016-03-18 12:21:23 -0500158{
Aaron Durbin7f8afe02016-03-18 12:21:23 -0500159 struct rmod_stage_load rsl = {
160 .cbmem_id = CBMEM_ID_AFTER_CAR,
Aaron Durbind0084132016-11-29 15:52:08 -0600161 .prog = prog,
Aaron Durbin7f8afe02016-03-18 12:21:23 -0500162 };
163
Aaron Durbind0084132016-11-29 15:52:08 -0600164 if (prog_locate(prog))
Keith Short70064582019-05-06 16:12:57 -0600165 die_with_post_code(POST_INVALID_ROM,
166 "Failed to locate after CAR program.\n");
Aaron Durbin7f8afe02016-03-18 12:21:23 -0500167 if (rmodule_stage_load(&rsl))
Keith Short70064582019-05-06 16:12:57 -0600168 die_with_post_code(POST_INVALID_ROM,
169 "Failed to load after CAR program.\n");
Aaron Durbin7f8afe02016-03-18 12:21:23 -0500170
171 /* Set the stack pointer within parameters of the program loaded. */
172 if (rsl.params == NULL)
Keith Short70064582019-05-06 16:12:57 -0600173 die_with_post_code(POST_INVALID_ROM,
174 "No parameters found in after CAR program.\n");
Aaron Durbin7f8afe02016-03-18 12:21:23 -0500175
Kyösti Mälkkia7421fb2017-09-05 22:43:05 +0300176 finalize_load(rsl.params, pcf->stack);
Aaron Durbindd95e002016-03-31 13:36:33 -0500177
Subrata Banik90f750b2019-06-11 17:52:06 +0530178 stage_cache_add(STAGE_POSTCAR, prog);
Aaron Durbind0084132016-11-29 15:52:08 -0600179}
180
181void run_postcar_phase(struct postcar_frame *pcf)
182{
183 struct prog prog =
Philipp Deppenwiese01797b12018-11-08 10:39:39 +0100184 PROG_INIT(PROG_POSTCAR, CONFIG_CBFS_PREFIX "/postcar");
Aaron Durbind0084132016-11-29 15:52:08 -0600185
186 postcar_commit_mtrrs(pcf);
187
Julius Wernercd49cce2019-03-05 16:53:33 -0800188 if (!CONFIG(NO_STAGE_CACHE) &&
Kyösti Mälkkia7421fb2017-09-05 22:43:05 +0300189 romstage_handoff_is_resume()) {
Aaron Durbind0084132016-11-29 15:52:08 -0600190 stage_cache_load_stage(STAGE_POSTCAR, &prog);
Aaron Durbinc546c762018-04-23 14:55:09 -0600191 /* This is here to allow platforms to pass different stack
192 parameters between S3 resume and normal boot. On the
193 platforms where the values are the same it's a nop. */
Kyösti Mälkkia7421fb2017-09-05 22:43:05 +0300194 finalize_load(prog.arg, pcf->stack);
195 } else
Aaron Durbind0084132016-11-29 15:52:08 -0600196 load_postcar_cbfs(&prog, pcf);
197
Subrata Banik2847e1e2019-02-25 20:31:22 +0530198 /* As postcar exist, it's end of romstage here */
199 timestamp_add_now(TS_END_ROMSTAGE);
200
Aaron Durbin7f8afe02016-03-18 12:21:23 -0500201 prog_run(&prog);
202}