blob: f5de5c345d3df8817408d4a2feed349feec3b22b [file] [log] [blame]
Patrick Georgiac959032020-05-05 22:49:26 +02001/* SPDX-License-Identifier: GPL-2.0-or-later */
Andrey Petrov465fc132016-02-25 14:16:33 -08002
Arthur Heymansfdf6d122022-05-17 13:07:30 +02003#include <arch/null_breakpoint.h>
Aaron Durbinb4302502016-07-17 17:04:37 -05004#include <arch/symbols.h>
Aaron Durbin31be2c92016-12-03 22:08:20 -06005#include <assert.h>
Aaron Durbind04639b2016-07-17 23:23:59 -05006#include <cbfs.h>
Aaron Durbin27928682016-07-15 22:32:28 -05007#include <cbmem.h>
Patrick Rudolphf677d172018-10-01 19:17:11 +02008#include <cf9_reset.h>
Andrey Petrov465fc132016-02-25 14:16:33 -08009#include <console/console.h>
Furquan Shaikh5aea5882016-07-30 18:10:05 -070010#include <elog.h>
Andrey Petrov465fc132016-02-25 14:16:33 -080011#include <fsp/api.h>
12#include <fsp/util.h>
13#include <memrange.h>
Arthur Heymansfdf6d122022-05-17 13:07:30 +020014#include <mode_switch.h>
Aaron Durbindecd0622017-12-15 12:26:40 -070015#include <mrc_cache.h>
Aaron Durbind04639b2016-07-17 23:23:59 -050016#include <program_loading.h>
Aaron Durbinb4302502016-07-17 17:04:37 -050017#include <romstage_handoff.h>
Arthur Heymansfdf6d122022-05-17 13:07:30 +020018#include <security/tpm/tspi.h>
19#include <security/vboot/antirollback.h>
20#include <security/vboot/vboot_common.h>
Andrey Petrov465fc132016-02-25 14:16:33 -080021#include <string.h>
Aaron Durbind04639b2016-07-17 23:23:59 -050022#include <symbols.h>
Andrey Petrov465fc132016-02-25 14:16:33 -080023#include <timestamp.h>
Elyes HAOUASbd1683d2019-05-15 21:05:37 +020024#include <types.h>
Arthur Heymansfdf6d122022-05-17 13:07:30 +020025#include <vb2_api.h>
Andrey Petrov465fc132016-02-25 14:16:33 -080026
Subrata Banik30a01142023-03-22 00:35:42 +053027#if CONFIG(SOC_INTEL_COMMON_BASECODE_RAMTOP)
28#include <intelbasecode/ramtop.h>
Subrata Banikdbfbfaf2023-02-28 07:01:26 +000029#endif
30
Kyösti Mälkkic9871502019-09-03 07:03:39 +030031static uint8_t temp_ram[CONFIG_FSP_TEMP_RAM_SIZE] __aligned(sizeof(uint64_t));
32
Subrata Banikf31ab7a2023-06-19 12:07:29 +000033/*
34 * Helper function to store the MRC cache version into CBMEM
35 *
36 * ramstage uses either the MRC version or FSP-M version (depending on the config)
37 * when updating the MRC cache
38 */
39static void do_cbmem_version_entry(uint32_t cbmem_id, uint32_t version)
40{
41 uint32_t *cbmem_version_entry = cbmem_add(cbmem_id, sizeof(version));
42 if (!cbmem_version_entry) {
43 printk(BIOS_ERR, "Failed to add %s version to cbmem.\n",
44 CONFIG(MRC_CACHE_USING_MRC_VERSION) ? "MRC" : "FSP-M");
45 return;
46 }
47 *cbmem_version_entry = version;
48}
49
Subrata Banik79274e012023-06-19 11:32:19 +000050static void do_fsp_post_memory_init(bool s3wake, uint32_t version)
Aaron Durbinf0ec8242016-07-18 11:24:36 -050051{
52 struct range_entry fsp_mem;
Subrata Banikf31ab7a2023-06-19 12:07:29 +000053 uint32_t cbmem_id = CONFIG(MRC_CACHE_USING_MRC_VERSION) ? CBMEM_ID_MRC_VERSION :
54 CBMEM_ID_FSPM_VERSION;
Aaron Durbinb4302502016-07-17 17:04:37 -050055
Michael Niewöhnerbc1dbb32019-10-24 22:58:25 +020056 fsp_find_reserved_memory(&fsp_mem);
Aaron Durbinb4302502016-07-17 17:04:37 -050057
58 /* initialize cbmem by adding FSP reserved memory first thing */
59 if (!s3wake) {
60 cbmem_initialize_empty_id_size(CBMEM_ID_FSP_RESERVED_MEMORY,
61 range_entry_size(&fsp_mem));
62 } else if (cbmem_initialize_id_size(CBMEM_ID_FSP_RESERVED_MEMORY,
63 range_entry_size(&fsp_mem))) {
Julius Wernercd49cce2019-03-05 16:53:33 -080064 if (CONFIG(HAVE_ACPI_RESUME)) {
Julius Wernere9665952022-01-21 17:06:20 -080065 printk(BIOS_ERR, "Failed to recover CBMEM in S3 resume.\n");
Aaron Durbinb4302502016-07-17 17:04:37 -050066 /* Failed S3 resume, reset to come up cleanly */
Patrick Rudolphf677d172018-10-01 19:17:11 +020067 /* FIXME: A "system" reset is likely enough: */
68 full_reset();
Aaron Durbinb4302502016-07-17 17:04:37 -050069 }
70 }
71
72 /* make sure FSP memory is reserved in cbmem */
73 if (range_entry_base(&fsp_mem) !=
74 (uintptr_t)cbmem_find(CBMEM_ID_FSP_RESERVED_MEMORY))
Lee Leahy9671faa2016-07-24 18:18:52 -070075 die("Failed to accommodate FSP reserved memory request!\n");
Aaron Durbinb4302502016-07-17 17:04:37 -050076
Subrata Banike48f24d2023-08-31 14:38:38 +000077 if (CONFIG(CACHE_MRC_SETTINGS) && !s3wake) {
Subrata Banikf31ab7a2023-06-19 12:07:29 +000078 do_cbmem_version_entry(cbmem_id, version);
Subrata Banike48f24d2023-08-31 14:38:38 +000079 if (!CONFIG(FSP_NVS_DATA_POST_SILICON_INIT))
80 save_memory_training_data();
81 }
Aaron Durbinb4302502016-07-17 17:04:37 -050082
Martin Roth74f18772023-09-03 21:38:29 -060083 /* Create romstage handoff information */
Aaron Durbin77e13992016-11-29 17:43:04 -060084 romstage_handoff_init(s3wake);
Aaron Durbinb4302502016-07-17 17:04:37 -050085}
86
Subrata Banik79274e012023-06-19 11:32:19 +000087static void fsp_fill_mrc_cache(FSPM_ARCH_UPD *arch_upd, uint32_t version)
Aaron Durbinb4302502016-07-17 17:04:37 -050088{
Aaron Durbin31be2c92016-12-03 22:08:20 -060089 void *data;
Shelley Chenad9cd682020-07-23 16:10:52 -070090 size_t mrc_size;
Aaron Durbinb4302502016-07-17 17:04:37 -050091
Patrick Rudolph31218a42020-11-30 15:50:06 +010092 arch_upd->NvsBufferPtr = 0;
Aaron Durbinf0ec8242016-07-18 11:24:36 -050093
Julius Wernercd49cce2019-03-05 16:53:33 -080094 if (!CONFIG(CACHE_MRC_SETTINGS))
Aaron Durbinf0ec8242016-07-18 11:24:36 -050095 return;
96
Aaron Durbin31be2c92016-12-03 22:08:20 -060097 /* Assume boot device is memory mapped. */
Julius Wernercd49cce2019-03-05 16:53:33 -080098 assert(CONFIG(BOOT_DEVICE_MEMORY_MAPPED));
Aaron Durbin31be2c92016-12-03 22:08:20 -060099
Subrata Banik79274e012023-06-19 11:32:19 +0000100 data = mrc_cache_current_mmap_leak(MRC_TRAINING_DATA, version,
Shelley Chenad9cd682020-07-23 16:10:52 -0700101 &mrc_size);
Aaron Durbin31be2c92016-12-03 22:08:20 -0600102 if (data == NULL)
103 return;
104
Aaron Durbinf0ec8242016-07-18 11:24:36 -0500105 /* MRC cache found */
Patrick Rudolph31218a42020-11-30 15:50:06 +0100106 arch_upd->NvsBufferPtr = (uintptr_t)data;
Aamir Bohra69cd62c2018-01-08 11:01:34 +0530107
Subrata Banik05937082023-03-06 08:18:24 +0000108 printk(BIOS_SPEW, "MRC cache found, size %zu bytes\n", mrc_size);
Aaron Durbinf0ec8242016-07-18 11:24:36 -0500109}
110
Aaron Durbin02e504c2016-07-18 11:53:10 -0500111static enum cb_err check_region_overlap(const struct memranges *ranges,
112 const char *description,
113 uintptr_t begin, uintptr_t end)
Aaron Durbinf0ec8242016-07-18 11:24:36 -0500114{
Aaron Durbin02e504c2016-07-18 11:53:10 -0500115 const struct range_entry *r;
116
117 memranges_each_entry(r, ranges) {
118 if (end <= range_entry_base(r))
119 continue;
120 if (begin >= range_entry_end(r))
121 continue;
Lee Leahyb20d4ba2016-07-31 16:49:28 -0700122 printk(BIOS_CRIT, "'%s' overlaps currently running program: "
Aaron Durbin02e504c2016-07-18 11:53:10 -0500123 "[%p, %p)\n", description, (void *)begin, (void *)end);
124 return CB_ERR;
125 }
126
127 return CB_SUCCESS;
128}
Kyösti Mälkkic9871502019-09-03 07:03:39 +0300129
Aamir Bohra6d569e0c2018-08-27 13:36:15 +0530130static enum cb_err setup_fsp_stack_frame(FSPM_ARCH_UPD *arch_upd,
131 const struct memranges *memmap)
Aaron Durbin02e504c2016-07-18 11:53:10 -0500132{
133 uintptr_t stack_begin;
134 uintptr_t stack_end;
135
Aaron Durbinb4302502016-07-17 17:04:37 -0500136 /*
Aamir Bohra6d569e0c2018-08-27 13:36:15 +0530137 * FSPM_UPD passed here is populated with default values
138 * provided by the blob itself. We let FSPM use top of CAR
139 * region of the size it requests.
Aaron Durbinb4302502016-07-17 17:04:37 -0500140 */
Aaron Durbin02e504c2016-07-18 11:53:10 -0500141 stack_end = (uintptr_t)_car_region_end;
142 stack_begin = stack_end - arch_upd->StackSize;
Aaron Durbin02e504c2016-07-18 11:53:10 -0500143 if (check_region_overlap(memmap, "FSPM stack", stack_begin,
144 stack_end) != CB_SUCCESS)
145 return CB_ERR;
146
Patrick Rudolph31218a42020-11-30 15:50:06 +0100147 arch_upd->StackBase = stack_begin;
Aamir Bohra6d569e0c2018-08-27 13:36:15 +0530148 return CB_SUCCESS;
149}
150
151static enum cb_err fsp_fill_common_arch_params(FSPM_ARCH_UPD *arch_upd,
Subrata Banik79274e012023-06-19 11:32:19 +0000152 bool s3wake, uint32_t version,
Aamir Bohra6d569e0c2018-08-27 13:36:15 +0530153 const struct memranges *memmap)
154{
Kyösti Mälkkic9871502019-09-03 07:03:39 +0300155 /*
156 * FSP 2.1 version would use same stack as coreboot instead of
157 * setting up separate stack frame. FSP 2.1 would not relocate stack
158 * top and does not reinitialize stack pointer. The parameters passed
159 * as StackBase and StackSize are actually for temporary RAM and HOBs
160 * and are not related to FSP stack at all.
Felix Held414d7e42020-08-11 22:54:06 +0200161 * Non-CAR FSP 2.0 platforms pass a DRAM location for the FSP stack.
Kyösti Mälkkic9871502019-09-03 07:03:39 +0300162 */
Marx Wang708a11c2023-11-10 17:00:23 +0800163 static const char * const fsp_bootmode_strings[] = {
164 [FSP_BOOT_WITH_FULL_CONFIGURATION] = "boot with full config",
165 [FSP_BOOT_WITH_MINIMAL_CONFIGURATION] = "boot with minimal config",
166 [FSP_BOOT_ASSUMING_NO_CONFIGURATION_CHANGES] = "boot assuming no config change",
167 [FSP_BOOT_ON_S4_RESUME] = "boot on s4 resume",
168 [FSP_BOOT_ON_S3_RESUME] = "boot on s3 resume",
169 [FSP_BOOT_ON_FLASH_UPDATE] = "boot on flash update",
170 [FSP_BOOT_IN_RECOVERY_MODE] = "boot in recovery mode",
171 };
172
Felix Held414d7e42020-08-11 22:54:06 +0200173 if (CONFIG(FSP_USES_CB_STACK) || !ENV_CACHE_AS_RAM) {
Patrick Rudolph31218a42020-11-30 15:50:06 +0100174 arch_upd->StackBase = (uintptr_t)temp_ram;
Kyösti Mälkkic9871502019-09-03 07:03:39 +0300175 arch_upd->StackSize = sizeof(temp_ram);
176 } else if (setup_fsp_stack_frame(arch_upd, memmap)) {
Aamir Bohra6d569e0c2018-08-27 13:36:15 +0530177 return CB_ERR;
Kyösti Mälkkic9871502019-09-03 07:03:39 +0300178 }
Aaron Durbinb4302502016-07-17 17:04:37 -0500179
Subrata Banik79274e012023-06-19 11:32:19 +0000180 fsp_fill_mrc_cache(arch_upd, version);
Aaron Durbinb4302502016-07-17 17:04:37 -0500181
Aamir Bohra69cd62c2018-01-08 11:01:34 +0530182 /* Configure bootmode */
183 if (s3wake) {
Aamir Bohra69cd62c2018-01-08 11:01:34 +0530184 arch_upd->BootMode = FSP_BOOT_ON_S3_RESUME;
185 } else {
186 if (arch_upd->NvsBufferPtr)
187 arch_upd->BootMode =
188 FSP_BOOT_ASSUMING_NO_CONFIGURATION_CHANGES;
189 else
190 arch_upd->BootMode = FSP_BOOT_WITH_FULL_CONFIGURATION;
191 }
Aaron Durbin02e504c2016-07-18 11:53:10 -0500192
Marx Wang708a11c2023-11-10 17:00:23 +0800193 if (arch_upd->BootMode < ARRAY_SIZE(fsp_bootmode_strings) &&
194 fsp_bootmode_strings[arch_upd->BootMode] != NULL)
195 printk(BIOS_SPEW, "bootmode is set to: %d (%s)\n", arch_upd->BootMode,
196 fsp_bootmode_strings[arch_upd->BootMode]);
197 else
198 printk(BIOS_SPEW, "bootmode is set to: %d (unknown mode)\n", arch_upd->BootMode);
Aamir Bohra276c06a2017-12-26 17:54:45 +0530199
Aaron Durbin02e504c2016-07-18 11:53:10 -0500200 return CB_SUCCESS;
Aaron Durbinb4302502016-07-17 17:04:37 -0500201}
202
Aaron Durbin64031672018-04-21 14:45:32 -0600203__weak
Aaron Durbina3cecb22017-04-25 21:58:10 -0500204uint8_t fsp_memory_mainboard_version(void)
205{
206 return 0;
207}
208
Aaron Durbin64031672018-04-21 14:45:32 -0600209__weak
Aaron Durbina3cecb22017-04-25 21:58:10 -0500210uint8_t fsp_memory_soc_version(void)
211{
212 return 0;
213}
214
215/*
216 * Allow SoC and/or mainboard to bump the revision of the FSP setting
217 * number. The FSP spec uses the low 8 bits as the build number. Take over
218 * bits 3:0 for the SoC setting and bits 7:4 for the mainboard. That way
219 * a tweak in the settings will bump the version used to track the cached
220 * setting which triggers retraining when the FSP version hasn't changed, but
221 * the SoC or mainboard settings have.
222 */
223static uint32_t fsp_memory_settings_version(const struct fsp_header *hdr)
224{
225 /* Use the full FSP version by default. */
Julian Schroeder8a576f62021-11-02 16:32:28 -0500226 uint32_t ver = hdr->image_revision;
Aaron Durbina3cecb22017-04-25 21:58:10 -0500227
Julius Wernercd49cce2019-03-05 16:53:33 -0800228 if (!CONFIG(FSP_PLATFORM_MEMORY_SETTINGS_VERSIONS))
Aaron Durbina3cecb22017-04-25 21:58:10 -0500229 return ver;
230
231 ver &= ~0xff;
232 ver |= (0xf & fsp_memory_mainboard_version()) << 4;
233 ver |= (0xf & fsp_memory_soc_version()) << 0;
234
235 return ver;
236}
237
Aaron Durbinecbfa992020-05-15 17:01:58 -0600238struct fspm_context {
239 struct fsp_header header;
240 struct memranges memmap;
241};
242
Subrata Banik79274e012023-06-19 11:32:19 +0000243/*
244 * Helper function to read MRC version
245 *
246 * There are multiple ways to read the MRC version using
247 * Intel FSP. Currently the only supported method to get the
248 * MRC version is by reading the FSP_PRODUCDER_DATA_TABLES
249 * from the FSP-M binary (by parsing the FSP header).
250 */
251static uint32_t fsp_mrc_version(void)
252{
253 uint32_t ver = 0;
254#if CONFIG(MRC_CACHE_USING_MRC_VERSION)
255 size_t fspm_blob_size;
Jonathon Halleb834d92023-09-27 12:50:59 -0400256 const char *fspm_cbfs = soc_select_fsp_m_cbfs();
257 void *fspm_blob_file = cbfs_map(fspm_cbfs, &fspm_blob_size);
Subrata Banik79274e012023-06-19 11:32:19 +0000258 if (!fspm_blob_file)
259 return 0;
260
261 FSP_PRODUCER_DATA_TABLES *ft = fspm_blob_file + FSP_HDR_OFFSET;
262 FSP_PRODUCER_DATA_TYPE2 *table2 = &ft->FspProduceDataType2;
263 size_t mrc_version_size = sizeof(table2->MrcVersion);
264 for (size_t i = 0; i < mrc_version_size; i++) {
265 ver |= (table2->MrcVersion[i] << ((mrc_version_size - 1) - i) * 8);
266 }
267 cbfs_unmap(fspm_blob_file);
268#endif
269 return ver;
270}
271
Aaron Durbinecbfa992020-05-15 17:01:58 -0600272static void do_fsp_memory_init(const struct fspm_context *context, bool s3wake)
Andrey Petrov465fc132016-02-25 14:16:33 -0800273{
Brandon Breitensteinc31ba0e2016-07-27 17:34:45 -0700274 uint32_t status;
Andrey Petrov465fc132016-02-25 14:16:33 -0800275 fsp_memory_init_fn fsp_raminit;
Brandon Breitensteinc31ba0e2016-07-27 17:34:45 -0700276 FSPM_UPD fspm_upd, *upd;
277 FSPM_ARCH_UPD *arch_upd;
Subrata Banik79274e012023-06-19 11:32:19 +0000278 uint32_t version;
Aaron Durbinecbfa992020-05-15 17:01:58 -0600279 const struct fsp_header *hdr = &context->header;
280 const struct memranges *memmap = &context->memmap;
Andrey Petrov465fc132016-02-25 14:16:33 -0800281
lilacious40cb3fe2023-06-21 23:24:14 +0200282 post_code(POSTCODE_MEM_PREINIT_PREP_START);
Andrey Petrov465fc132016-02-25 14:16:33 -0800283
Subrata Banik79274e012023-06-19 11:32:19 +0000284 if (CONFIG(MRC_CACHE_USING_MRC_VERSION))
285 version = fsp_mrc_version();
286 else
287 version = fsp_memory_settings_version(hdr);
Aaron Durbina3cecb22017-04-25 21:58:10 -0500288
Patrick Rudolph31218a42020-11-30 15:50:06 +0100289 upd = (FSPM_UPD *)(uintptr_t)(hdr->cfg_region_offset + hdr->image_base);
Andrey Petrov465fc132016-02-25 14:16:33 -0800290
Felix Helda0955952021-02-02 21:30:25 +0100291 /*
292 * Verify UPD region size. We don't have malloc before ramstage, so we
293 * use a static buffer for the FSP-M UPDs which is sizeof(FSPM_UPD)
294 * bytes long, since that is the value known at compile time. If
295 * hdr->cfg_region_size is bigger than that, not all UPD defaults will
296 * be copied, so it'll contain random data at the end, so we just call
297 * die() in that case. If hdr->cfg_region_size is smaller than that,
298 * there's a mismatch between the FSP and the header, but since it will
299 * copy the full UPD defaults to the buffer, we try to continue and
300 * hope that there was no incompatible change in the UPDs.
301 */
302 if (hdr->cfg_region_size > sizeof(FSPM_UPD))
303 die("FSP-M UPD size is larger than FSPM_UPD struct size.\n");
304 if (hdr->cfg_region_size < sizeof(FSPM_UPD))
305 printk(BIOS_ERR, "FSP-M UPD size is smaller than FSPM_UPD struct size. "
306 "Check if the FSP binary matches the FSP headers.\n");
307
Felix Held88995982021-01-28 22:43:52 +0100308 fsp_verify_upd_header_signature(upd->FspUpdHeader.Signature, FSPM_UPD_SIGNATURE);
Andrey Petrov465fc132016-02-25 14:16:33 -0800309
310 /* Copy the default values from the UPD area */
311 memcpy(&fspm_upd, upd, sizeof(fspm_upd));
312
Aaron Durbin02e504c2016-07-18 11:53:10 -0500313 arch_upd = &fspm_upd.FspmArchUpd;
314
Aaron Durbin27928682016-07-15 22:32:28 -0500315 /* Reserve enough memory under TOLUD to save CBMEM header */
Aaron Durbin02e504c2016-07-18 11:53:10 -0500316 arch_upd->BootLoaderTolumSize = cbmem_overhead_size();
Aaron Durbin27928682016-07-15 22:32:28 -0500317
Aaron Durbinb4302502016-07-17 17:04:37 -0500318 /* Fill common settings on behalf of chipset. */
Subrata Banik79274e012023-06-19 11:32:19 +0000319 if (fsp_fill_common_arch_params(arch_upd, s3wake, version,
Aaron Durbin02e504c2016-07-18 11:53:10 -0500320 memmap) != CB_SUCCESS)
lilacious40cb3fe2023-06-21 23:24:14 +0200321 die_with_post_code(POSTCODE_INVALID_VENDOR_BINARY,
Keith Shortbb41aba2019-05-16 14:07:43 -0600322 "FSPM_ARCH_UPD not found!\n");
Aaron Durbinb4302502016-07-17 17:04:37 -0500323
Subrata Banik30a01142023-03-22 00:35:42 +0530324 /* Early caching of RAMTOP region if valid mrc cache data is found */
325#if (CONFIG(SOC_INTEL_COMMON_BASECODE_RAMTOP))
Subrata Banikdbfbfaf2023-02-28 07:01:26 +0000326 if (arch_upd->NvsBufferPtr)
Subrata Banik30a01142023-03-22 00:35:42 +0530327 early_ramtop_enable_cache_range();
Subrata Banikdbfbfaf2023-02-28 07:01:26 +0000328#endif
329
Andrey Petrov465fc132016-02-25 14:16:33 -0800330 /* Give SoC and mainboard a chance to update the UPD */
Subrata Banik79274e012023-06-19 11:32:19 +0000331 platform_fsp_memory_init_params_cb(&fspm_upd, version);
Andrey Petrov465fc132016-02-25 14:16:33 -0800332
Furquan Shaikhdbce8ba2020-06-05 19:17:00 -0700333 /*
334 * For S3 resume case, if valid mrc cache data is not found or
335 * RECOVERY_MRC_CACHE hash verification fails, the S3 data
336 * pointer would be null and S3 resume fails with fsp-m
337 * returning error. Invoking a reset here saves time.
338 */
339 if (s3wake && !arch_upd->NvsBufferPtr)
340 /* FIXME: A "system" reset is likely enough: */
341 full_reset();
342
Julius Wernercd49cce2019-03-05 16:53:33 -0800343 if (CONFIG(MMA))
Pratik Prajapatiffc934d2016-11-18 14:36:34 -0800344 setup_mma(&fspm_upd.FspmConfig);
345
lilacious40cb3fe2023-06-21 23:24:14 +0200346 post_code(POSTCODE_MEM_PREINIT_PREP_END);
Furquan Shaikh585210a2018-10-16 11:54:37 -0700347
Andrey Petrov465fc132016-02-25 14:16:33 -0800348 /* Call FspMemoryInit */
Julian Schroeder8a576f62021-11-02 16:32:28 -0500349 fsp_raminit = (void *)(uintptr_t)(hdr->image_base + hdr->fsp_memory_init_entry_offset);
Lee Leahyac3b0a62016-07-27 07:40:25 -0700350 fsp_debug_before_memory_init(fsp_raminit, upd, &fspm_upd);
Andrey Petrov465fc132016-02-25 14:16:33 -0800351
Arthur Heymansfdf6d122022-05-17 13:07:30 +0200352 /* FSP disables the interrupt handler so remove debug exceptions temporarily */
353 null_breakpoint_disable();
lilacious40cb3fe2023-06-21 23:24:14 +0200354 post_code(POSTCODE_FSP_MEMORY_INIT);
Andrey Petrov465fc132016-02-25 14:16:33 -0800355 timestamp_add_now(TS_FSP_MEMORY_INIT_START);
Patrick Rudolph31218a42020-11-30 15:50:06 +0100356 if (ENV_X86_64 && CONFIG(PLATFORM_USES_FSP2_X86_32))
Patrick Rudolph40beb362020-12-01 10:08:38 +0100357 status = protected_mode_call_2arg(fsp_raminit,
358 (uintptr_t)&fspm_upd,
359 (uintptr_t)fsp_get_hob_list_ptr());
360 else
361 status = fsp_raminit(&fspm_upd, fsp_get_hob_list_ptr());
Arthur Heymansfdf6d122022-05-17 13:07:30 +0200362 null_breakpoint_init();
Patrick Rudolph40beb362020-12-01 10:08:38 +0100363
lilacious40cb3fe2023-06-21 23:24:14 +0200364 post_code(POSTCODE_FSP_MEMORY_EXIT);
Andrey Petrov465fc132016-02-25 14:16:33 -0800365 timestamp_add_now(TS_FSP_MEMORY_INIT_END);
366
Lee Leahy9671faa2016-07-24 18:18:52 -0700367 /* Handle any errors returned by FspMemoryInit */
Aaron Durbinf41f2aa2016-07-18 12:03:58 -0500368 fsp_handle_reset(status);
Lee Leahy9671faa2016-07-24 18:18:52 -0700369 if (status != FSP_SUCCESS) {
lilacious40cb3fe2023-06-21 23:24:14 +0200370 die_with_post_code(POSTCODE_RAM_FAILURE,
Angel Pons2b1f8d42022-01-01 17:20:00 +0100371 "FspMemoryInit returned with error 0x%08x!\n", status);
Lee Leahy9671faa2016-07-24 18:18:52 -0700372 }
Aaron Durbinf41f2aa2016-07-18 12:03:58 -0500373
Subrata Banik79274e012023-06-19 11:32:19 +0000374 do_fsp_post_memory_init(s3wake, version);
Matthew Garrett78b58a42018-07-28 16:53:16 -0700375
376 /*
377 * fsp_debug_after_memory_init() checks whether the end of the tolum
378 * region is the same as the top of cbmem, so must be called here
379 * after cbmem has been initialised in do_fsp_post_memory_init().
380 */
381 fsp_debug_after_memory_init(status);
Andrey Petrov465fc132016-02-25 14:16:33 -0800382}
383
Julius Werner8205ce62021-03-10 17:25:01 -0800384static void *fspm_allocator(void *arg, size_t size, const union cbfs_mdata *unused)
Aaron Durbind04639b2016-07-17 23:23:59 -0500385{
Julius Werner8205ce62021-03-10 17:25:01 -0800386 const struct fsp_load_descriptor *fspld = arg;
Aaron Durbinecbfa992020-05-15 17:01:58 -0600387 struct fspm_context *context = fspld->arg;
Aaron Durbinecbfa992020-05-15 17:01:58 -0600388 struct memranges *memmap = &context->memmap;
Aaron Durbind04639b2016-07-17 23:23:59 -0500389
Aaron Durbinecbfa992020-05-15 17:01:58 -0600390 /* Non XIP FSP-M uses FSP-M address */
Julius Werner8205ce62021-03-10 17:25:01 -0800391 uintptr_t fspm_begin = (uintptr_t)CONFIG_FSP_M_ADDR;
392 uintptr_t fspm_end = fspm_begin + size;
Aaron Durbinecbfa992020-05-15 17:01:58 -0600393
394 if (check_region_overlap(memmap, "FSPM", fspm_begin, fspm_end) != CB_SUCCESS)
Julius Werner8205ce62021-03-10 17:25:01 -0800395 return NULL;
Aaron Durbinecbfa992020-05-15 17:01:58 -0600396
Julius Werner8205ce62021-03-10 17:25:01 -0800397 return (void *)fspm_begin;
Aaron Durbind04639b2016-07-17 23:23:59 -0500398}
399
Raul E Rangel15928462021-11-05 10:29:24 -0600400void preload_fspm(void)
401{
402 if (!CONFIG(CBFS_PRELOAD))
403 return;
404
Jonathon Halleb834d92023-09-27 12:50:59 -0400405 const char *fspm_cbfs = soc_select_fsp_m_cbfs();
406 printk(BIOS_DEBUG, "Preloading %s\n", fspm_cbfs);
407 cbfs_preload(fspm_cbfs);
Raul E Rangel15928462021-11-05 10:29:24 -0600408}
409
Lee Leahy9671faa2016-07-24 18:18:52 -0700410void fsp_memory_init(bool s3wake)
Andrey Petrov465fc132016-02-25 14:16:33 -0800411{
Marshall Dawsone3aa4242019-10-16 21:53:21 -0600412 struct range_entry prog_ranges[2];
Aaron Durbinecbfa992020-05-15 17:01:58 -0600413 struct fspm_context context;
Jonathon Halleb834d92023-09-27 12:50:59 -0400414 const char *fspm_cbfs = soc_select_fsp_m_cbfs();
Aaron Durbinecbfa992020-05-15 17:01:58 -0600415 struct fsp_load_descriptor fspld = {
Jonathon Halleb834d92023-09-27 12:50:59 -0400416 .fsp_prog = PROG_INIT(PROG_REFCODE, fspm_cbfs),
Aaron Durbinecbfa992020-05-15 17:01:58 -0600417 .arg = &context,
418 };
419 struct fsp_header *hdr = &context.header;
420 struct memranges *memmap = &context.memmap;
Andrey Petrov465fc132016-02-25 14:16:33 -0800421
Julius Werner8205ce62021-03-10 17:25:01 -0800422 /* For FSP-M XIP we leave alloc NULL to get a direct mapping to flash. */
423 if (!CONFIG(FSP_M_XIP))
424 fspld.alloc = fspm_allocator;
425
Kyösti Mälkki7f50afb2019-09-11 17:12:26 +0300426 elog_boot_notify(s3wake);
Furquan Shaikh5aea5882016-07-30 18:10:05 -0700427
Aaron Durbin02e504c2016-07-18 11:53:10 -0500428 /* Build up memory map of romstage address space including CAR. */
Aaron Durbinecbfa992020-05-15 17:01:58 -0600429 memranges_init_empty(memmap, &prog_ranges[0], ARRAY_SIZE(prog_ranges));
Marshall Dawsone3aa4242019-10-16 21:53:21 -0600430 if (ENV_CACHE_AS_RAM)
Aaron Durbinecbfa992020-05-15 17:01:58 -0600431 memranges_insert(memmap, (uintptr_t)_car_region_start,
Marshall Dawsone3aa4242019-10-16 21:53:21 -0600432 _car_unallocated_start - _car_region_start, 0);
Aaron Durbinecbfa992020-05-15 17:01:58 -0600433 memranges_insert(memmap, (uintptr_t)_program, REGION_SIZE(program), 0);
Aaron Durbin02e504c2016-07-18 11:53:10 -0500434
Martin Roth146508d2021-04-30 16:45:08 -0600435 timestamp_add_now(TS_FSP_MEMORY_INIT_LOAD);
Aaron Durbinecbfa992020-05-15 17:01:58 -0600436 if (fsp_load_component(&fspld, hdr) != CB_SUCCESS)
437 die("FSPM not available or failed to load!\n");
Andrey Petrov465fc132016-02-25 14:16:33 -0800438
Julius Werner8205ce62021-03-10 17:25:01 -0800439 if (CONFIG(FSP_M_XIP) && (uintptr_t)prog_start(&fspld.fsp_prog) != hdr->image_base)
440 die("FSPM XIP base does not match: %p vs %p\n",
441 (void *)(uintptr_t)hdr->image_base, prog_start(&fspld.fsp_prog));
442
Jakub Czapigaad6157e2022-02-15 11:50:31 +0100443 timestamp_add_now(TS_INITRAM_START);
Kyösti Mälkki216db612019-09-11 09:57:14 +0300444
Aaron Durbinecbfa992020-05-15 17:01:58 -0600445 do_fsp_memory_init(&context, s3wake);
Kyösti Mälkki0889e932019-08-18 07:40:43 +0300446
Jakub Czapigaad6157e2022-02-15 11:50:31 +0100447 timestamp_add_now(TS_INITRAM_END);
Andrey Petrov465fc132016-02-25 14:16:33 -0800448}