xref: /aosp_15_r20/external/coreboot/src/drivers/intel/fsp2_0/memory_init.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include <arch/null_breakpoint.h>
4 #include <arch/symbols.h>
5 #include <assert.h>
6 #include <cbfs.h>
7 #include <cbmem.h>
8 #include <cf9_reset.h>
9 #include <console/console.h>
10 #include <elog.h>
11 #include <fsp/api.h>
12 #include <fsp/util.h>
13 #include <memrange.h>
14 #include <mode_switch.h>
15 #include <mrc_cache.h>
16 #include <program_loading.h>
17 #include <romstage_handoff.h>
18 #include <security/tpm/tspi.h>
19 #include <security/vboot/antirollback.h>
20 #include <security/vboot/vboot_common.h>
21 #include <string.h>
22 #include <symbols.h>
23 #include <timestamp.h>
24 #include <types.h>
25 #include <vb2_api.h>
26 
27 #if CONFIG(SOC_INTEL_COMMON_BASECODE_RAMTOP)
28 #include <intelbasecode/ramtop.h>
29 #endif
30 
31 /* Callbacks for SoC/Mainboard specific overrides */
platform_fsp_memory_multi_phase_init_cb(uint32_t phase_index)32 void __weak platform_fsp_memory_multi_phase_init_cb(uint32_t phase_index)
33 {
34 	/* Leave for the SoC/Mainboard to implement if necessary. */
35 }
36 
37 static uint8_t temp_ram[CONFIG_FSP_TEMP_RAM_SIZE] __aligned(16);
38 
39 /*
40  * Helper function to store the MRC cache version into CBMEM
41  *
42  * ramstage uses either the MRC version or FSP-M version (depending on the config)
43  * when updating the MRC cache
44  */
do_cbmem_version_entry(uint32_t cbmem_id,uint32_t version)45 static void do_cbmem_version_entry(uint32_t cbmem_id, uint32_t version)
46 {
47 	uint32_t *cbmem_version_entry = cbmem_add(cbmem_id, sizeof(version));
48 	if (!cbmem_version_entry) {
49 		printk(BIOS_ERR, "Failed to add %s version to cbmem.\n",
50 				CONFIG(MRC_CACHE_USING_MRC_VERSION) ? "MRC" : "FSP-M");
51 		return;
52 	}
53 	*cbmem_version_entry = version;
54 }
55 
do_fsp_post_memory_init(bool s3wake,uint32_t version)56 static void do_fsp_post_memory_init(bool s3wake, uint32_t version)
57 {
58 	struct range_entry fsp_mem;
59 	uint32_t cbmem_id = CONFIG(MRC_CACHE_USING_MRC_VERSION) ? CBMEM_ID_MRC_VERSION :
60 					 CBMEM_ID_FSPM_VERSION;
61 
62 	fsp_find_reserved_memory(&fsp_mem);
63 
64 	/* initialize cbmem by adding FSP reserved memory first thing */
65 	if (!s3wake) {
66 		cbmem_initialize_empty_id_size(CBMEM_ID_FSP_RESERVED_MEMORY,
67 			range_entry_size(&fsp_mem));
68 	} else if (cbmem_initialize_id_size(CBMEM_ID_FSP_RESERVED_MEMORY,
69 				range_entry_size(&fsp_mem))) {
70 		if (CONFIG(HAVE_ACPI_RESUME)) {
71 			printk(BIOS_ERR, "Failed to recover CBMEM in S3 resume.\n");
72 			/* Failed S3 resume, reset to come up cleanly */
73 			/* FIXME: A "system" reset is likely enough: */
74 			full_reset();
75 		}
76 	}
77 
78 	/* make sure FSP memory is reserved in cbmem */
79 	if (range_entry_base(&fsp_mem) !=
80 		(uintptr_t)cbmem_find(CBMEM_ID_FSP_RESERVED_MEMORY))
81 		die("Failed to accommodate FSP reserved memory request!\n");
82 
83 	if (CONFIG(CACHE_MRC_SETTINGS) && !s3wake) {
84 		do_cbmem_version_entry(cbmem_id, version);
85 		if (!CONFIG(FSP_NVS_DATA_POST_SILICON_INIT))
86 			save_memory_training_data();
87 	}
88 
89 	/* Create romstage handoff information */
90 	romstage_handoff_init(s3wake);
91 }
92 
fsp_fill_mrc_cache(FSPM_ARCHx_UPD * arch_upd,uint32_t version)93 static void fsp_fill_mrc_cache(FSPM_ARCHx_UPD *arch_upd, uint32_t version)
94 {
95 	void *data;
96 	size_t mrc_size;
97 
98 	arch_upd->NvsBufferPtr = 0;
99 
100 	if (!CONFIG(CACHE_MRC_SETTINGS))
101 		return;
102 
103 	/* Assume boot device is memory mapped. */
104 	assert(CONFIG(BOOT_DEVICE_MEMORY_MAPPED));
105 
106 	data = mrc_cache_current_mmap_leak(MRC_TRAINING_DATA, version,
107 					   &mrc_size);
108 	if (data == NULL)
109 		return;
110 
111 	/* MRC cache found */
112 	arch_upd->NvsBufferPtr = (uintptr_t)data;
113 
114 	printk(BIOS_SPEW, "MRC cache found, size %zu bytes\n", mrc_size);
115 }
116 
check_region_overlap(const struct memranges * ranges,const char * description,uintptr_t begin,uintptr_t end)117 static enum cb_err check_region_overlap(const struct memranges *ranges,
118 					const char *description,
119 					uintptr_t begin, uintptr_t end)
120 {
121 	const struct range_entry *r;
122 
123 	memranges_each_entry(r, ranges) {
124 		if (end <= range_entry_base(r))
125 			continue;
126 		if (begin >= range_entry_end(r))
127 			continue;
128 		printk(BIOS_CRIT, "'%s' overlaps currently running program: "
129 			"[%p, %p)\n", description, (void *)begin, (void *)end);
130 		return CB_ERR;
131 	}
132 
133 	return CB_SUCCESS;
134 }
135 
setup_fsp_stack_frame(FSPM_ARCHx_UPD * arch_upd,const struct memranges * memmap)136 static enum cb_err setup_fsp_stack_frame(FSPM_ARCHx_UPD *arch_upd,
137 		const struct memranges *memmap)
138 {
139 	uintptr_t stack_begin;
140 	uintptr_t stack_end;
141 
142 	/*
143 	 * FSPM_UPD passed here is populated with default values
144 	 * provided by the blob itself. We let FSPM use top of CAR
145 	 * region of the size it requests.
146 	 */
147 	stack_end = (uintptr_t)_car_region_end;
148 	stack_begin = stack_end - arch_upd->StackSize;
149 	if (check_region_overlap(memmap, "FSPM stack", stack_begin,
150 				stack_end) != CB_SUCCESS)
151 		return CB_ERR;
152 
153 	arch_upd->StackBase = stack_begin;
154 	return CB_SUCCESS;
155 }
156 
fsp_fill_common_arch_params(FSPM_ARCHx_UPD * arch_upd,bool s3wake,uint32_t version,const struct memranges * memmap)157 static enum cb_err fsp_fill_common_arch_params(FSPM_ARCHx_UPD *arch_upd,
158 					bool s3wake, uint32_t version,
159 					const struct memranges *memmap)
160 {
161 	/*
162 	 * FSP 2.1 version would use same stack as coreboot instead of
163 	 * setting up separate stack frame. FSP 2.1 would not relocate stack
164 	 * top and does not reinitialize stack pointer. The parameters passed
165 	 * as StackBase and StackSize are actually for temporary RAM and HOBs
166 	 * and are not related to FSP stack at all.
167 	 * Non-CAR FSP 2.0 platforms pass a DRAM location for the FSP stack.
168 	 */
169 	static const char * const fsp_bootmode_strings[] = {
170 		[FSP_BOOT_WITH_FULL_CONFIGURATION] = "boot with full config",
171 		[FSP_BOOT_WITH_MINIMAL_CONFIGURATION] = "boot with minimal config",
172 		[FSP_BOOT_ASSUMING_NO_CONFIGURATION_CHANGES] = "boot assuming no config change",
173 		[FSP_BOOT_ON_S4_RESUME] = "boot on s4 resume",
174 		[FSP_BOOT_ON_S3_RESUME] = "boot on s3 resume",
175 		[FSP_BOOT_ON_FLASH_UPDATE] = "boot on flash update",
176 		[FSP_BOOT_IN_RECOVERY_MODE] = "boot in recovery mode",
177 	};
178 
179 	if (CONFIG(FSP_USES_CB_STACK) && ENV_RAMINIT
180 	    && CONFIG(FSP_SPEC_VIOLATION_XEON_SP_HEAP_WORKAROUND)) {
181 		DECLARE_REGION(fspm_heap);
182 		arch_upd->StackBase = (uintptr_t)_fspm_heap;
183 		arch_upd->StackSize = (size_t)REGION_SIZE(fspm_heap);
184 	} else if (CONFIG(FSP_USES_CB_STACK) || !ENV_CACHE_AS_RAM) {
185 		arch_upd->StackBase = (uintptr_t)temp_ram;
186 		arch_upd->StackSize = sizeof(temp_ram);
187 	} else if (setup_fsp_stack_frame(arch_upd, memmap)) {
188 		return CB_ERR;
189 	}
190 
191 	fsp_fill_mrc_cache(arch_upd, version);
192 
193 	/* Configure bootmode */
194 	if (s3wake) {
195 		arch_upd->BootMode = FSP_BOOT_ON_S3_RESUME;
196 	} else {
197 		if (arch_upd->NvsBufferPtr)
198 			arch_upd->BootMode =
199 				FSP_BOOT_ASSUMING_NO_CONFIGURATION_CHANGES;
200 		else
201 			arch_upd->BootMode = FSP_BOOT_WITH_FULL_CONFIGURATION;
202 	}
203 
204 	if (arch_upd->BootMode < ARRAY_SIZE(fsp_bootmode_strings) &&
205 		fsp_bootmode_strings[arch_upd->BootMode] != NULL)
206 		printk(BIOS_SPEW, "bootmode is set to: %d (%s)\n", arch_upd->BootMode,
207 			fsp_bootmode_strings[arch_upd->BootMode]);
208 	else
209 		printk(BIOS_SPEW, "bootmode is set to: %d (unknown mode)\n", arch_upd->BootMode);
210 
211 	return CB_SUCCESS;
212 }
213 
214 __weak
fsp_memory_mainboard_version(void)215 uint8_t fsp_memory_mainboard_version(void)
216 {
217 	return 0;
218 }
219 
220 __weak
fsp_memory_soc_version(void)221 uint8_t fsp_memory_soc_version(void)
222 {
223 	return 0;
224 }
225 
226 /*
227  * Allow SoC and/or mainboard to bump the revision of the FSP setting
228  * number. The FSP spec uses the low 8 bits as the build number. Take over
229  * bits 3:0 for the SoC setting and bits 7:4 for the mainboard. That way
230  * a tweak in the settings will bump the version used to track the cached
231  * setting which triggers retraining when the FSP version hasn't changed, but
232  * the SoC or mainboard settings have.
233  */
fsp_memory_settings_version(const struct fsp_header * hdr)234 static uint32_t fsp_memory_settings_version(const struct fsp_header *hdr)
235 {
236 	/* Use the full FSP version by default. */
237 	uint32_t ver = hdr->image_revision;
238 
239 	if (!CONFIG(FSP_PLATFORM_MEMORY_SETTINGS_VERSIONS))
240 		return ver;
241 
242 	ver &= ~0xff;
243 	ver |= (0xf & fsp_memory_mainboard_version()) << 4;
244 	ver |= (0xf & fsp_memory_soc_version()) << 0;
245 
246 	return ver;
247 }
248 
249 struct fspm_context {
250 	struct fsp_header header;
251 	struct memranges memmap;
252 };
253 
254 /*
255  * Helper function to read MRC version
256  *
257  * There are multiple ways to read the MRC version using
258  * Intel FSP. Currently the only supported method to get the
259  * MRC version is by reading the FSP_PRODUCDER_DATA_TABLES
260  * from the FSP-M binary (by parsing the FSP header).
261  */
fsp_mrc_version(const struct fsp_header * hdr)262 static uint32_t fsp_mrc_version(const struct fsp_header *hdr)
263 {
264 	uint32_t ver = 0;
265 #if CONFIG(MRC_CACHE_USING_MRC_VERSION)
266 	void *fspm_blob_file = (void *)(uintptr_t)hdr->image_base;
267 	FSP_PRODUCER_DATA_TABLES *ft = fspm_blob_file + FSP_HDR_OFFSET;
268 	FSP_PRODUCER_DATA_TYPE2 *table2 = &ft->FspProduceDataType2;
269 	size_t mrc_version_size = sizeof(table2->MrcVersion);
270 	for (size_t i = 0; i < mrc_version_size; i++) {
271 		ver |= (table2->MrcVersion[i] << ((mrc_version_size - 1) - i) * 8);
272 	}
273 #endif
274 	return ver;
275 }
276 
fspm_return_value_handler(const char * context,efi_return_status_t status,bool die_on_error)277 static void fspm_return_value_handler(const char *context, efi_return_status_t status,
278 		 bool die_on_error)
279 {
280 	if (status == FSP_SUCCESS)
281 		return;
282 
283 	fsp_handle_reset(status);
284 	if (die_on_error)
285 		fsp_die_with_post_code(status, POSTCODE_RAM_FAILURE, "%s error", context);
286 
287 	fsp_printk(status, BIOS_SPEW, "%s", context);
288 }
289 
fspm_multi_phase_init(const struct fsp_header * hdr)290 static void fspm_multi_phase_init(const struct fsp_header *hdr)
291 {
292 	efi_return_status_t status;
293 	fsp_multi_phase_init_fn fsp_multi_phase_init;
294 	struct fsp_multi_phase_params multi_phase_params;
295 	struct fsp_multi_phase_get_number_of_phases_params multi_phase_get_number;
296 
297 	if (!hdr->fsp_multi_phase_mem_init_entry_offset)
298 		return;
299 
300 	fsp_multi_phase_init = (fsp_multi_phase_init_fn)(uintptr_t)
301 		(hdr->image_base + hdr->fsp_multi_phase_mem_init_entry_offset);
302 
303 	post_code(POSTCODE_FSP_MULTI_PHASE_MEM_INIT_ENTRY);
304 	timestamp_add_now(TS_FSP_MULTI_PHASE_MEM_INIT_START);
305 
306 	/* Get number of phases */
307 	multi_phase_params.multi_phase_action = GET_NUMBER_OF_PHASES;
308 	multi_phase_params.phase_index = 0;
309 	multi_phase_params.multi_phase_param_ptr = &multi_phase_get_number;
310 	status = fsp_multi_phase_init(&multi_phase_params);
311 	fspm_return_value_handler("FspMultiPhaseMemInit NumberOfPhases", status, false);
312 
313 	/* Execute all phases */
314 	for (uint32_t i = 1; i <= multi_phase_get_number.number_of_phases; i++) {
315 		printk(BIOS_SPEW, "Executing Phase %u of FspMultiPhaseMemInit\n", i);
316 		/*
317 		 * Give SoC/mainboard a chance to perform any operation before
318 		 * Multi Phase Execution
319 		 */
320 		platform_fsp_memory_multi_phase_init_cb(i);
321 
322 		multi_phase_params.multi_phase_action = EXECUTE_PHASE;
323 		multi_phase_params.phase_index = i;
324 		multi_phase_params.multi_phase_param_ptr = NULL;
325 		status = fsp_multi_phase_init(&multi_phase_params);
326 		fspm_return_value_handler("FspMultiPhaseMemInit Execute", status, false);
327 	}
328 
329 	post_code(POSTCODE_FSP_MULTI_PHASE_MEM_INIT_EXIT);
330 	timestamp_add_now(TS_FSP_MULTI_PHASE_MEM_INIT_END);
331 }
332 
do_fsp_memory_init(const struct fspm_context * context,bool s3wake)333 static void do_fsp_memory_init(const struct fspm_context *context, bool s3wake)
334 {
335 	efi_return_status_t status;
336 	fsp_memory_init_fn fsp_raminit;
337 	FSPM_UPD fspm_upd, *upd;
338 	FSPM_ARCHx_UPD *arch_upd;
339 	uint32_t version;
340 	const struct fsp_header *hdr = &context->header;
341 	const struct memranges *memmap = &context->memmap;
342 
343 	post_code(POSTCODE_MEM_PREINIT_PREP_START);
344 
345 	if (CONFIG(MRC_CACHE_USING_MRC_VERSION))
346 		version = fsp_mrc_version(hdr);
347 	else
348 		version = fsp_memory_settings_version(hdr);
349 
350 	upd = (FSPM_UPD *)(uintptr_t)(hdr->cfg_region_offset + hdr->image_base);
351 
352 	/*
353 	 * Verify UPD region size. We don't have malloc before ramstage, so we
354 	 * use a static buffer for the FSP-M UPDs which is sizeof(FSPM_UPD)
355 	 * bytes long, since that is the value known at compile time. If
356 	 * hdr->cfg_region_size is bigger than that, not all UPD defaults will
357 	 * be copied, so it'll contain random data at the end, so we just call
358 	 * die() in that case. If hdr->cfg_region_size is smaller than that,
359 	 * there's a mismatch between the FSP and the header, but since it will
360 	 * copy the full UPD defaults to the buffer, we try to continue and
361 	 * hope that there was no incompatible change in the UPDs.
362 	 */
363 	if (hdr->cfg_region_size > sizeof(FSPM_UPD))
364 		die("FSP-M UPD size is larger than FSPM_UPD struct size.\n");
365 	if (hdr->cfg_region_size < sizeof(FSPM_UPD))
366 		printk(BIOS_ERR, "FSP-M UPD size is smaller than FSPM_UPD struct size. "
367 				"Check if the FSP binary matches the FSP headers.\n");
368 
369 	fsp_verify_upd_header_signature(upd->FspUpdHeader.Signature, FSPM_UPD_SIGNATURE);
370 
371 	/* Copy the default values from the UPD area */
372 	memcpy(&fspm_upd, upd, sizeof(fspm_upd));
373 
374 	arch_upd = &fspm_upd.FspmArchUpd;
375 
376 	/* Reserve enough memory under TOLUD to save CBMEM header */
377 	arch_upd->BootLoaderTolumSize = cbmem_overhead_size();
378 
379 	/* Fill common settings on behalf of chipset. */
380 	if (fsp_fill_common_arch_params(arch_upd, s3wake, version,
381 					memmap) != CB_SUCCESS)
382 		die_with_post_code(POSTCODE_INVALID_VENDOR_BINARY,
383 			"FSPM_ARCH_UPD not found!\n");
384 
385 	/* Early caching of RAMTOP region if valid mrc cache data is found */
386 #if (CONFIG(SOC_INTEL_COMMON_BASECODE_RAMTOP))
387 	if (arch_upd->NvsBufferPtr)
388 		early_ramtop_enable_cache_range();
389 #endif
390 
391 	/* Give SoC and mainboard a chance to update the UPD */
392 	platform_fsp_memory_init_params_cb(&fspm_upd, version);
393 
394 	/*
395 	 * For S3 resume case, if valid mrc cache data is not found or
396 	 * RECOVERY_MRC_CACHE hash verification fails, the S3 data
397 	 * pointer would be null and S3 resume fails with fsp-m
398 	 * returning error. Invoking a reset here saves time.
399 	 */
400 	if (s3wake && !arch_upd->NvsBufferPtr)
401 		/* FIXME: A "system" reset is likely enough: */
402 		full_reset();
403 
404 	if (CONFIG(MMA))
405 		setup_mma(&fspm_upd.FspmConfig);
406 
407 	post_code(POSTCODE_MEM_PREINIT_PREP_END);
408 
409 	/* Call FspMemoryInit */
410 	fsp_raminit = (void *)(uintptr_t)(hdr->image_base + hdr->fsp_memory_init_entry_offset);
411 	fsp_debug_before_memory_init(fsp_raminit, upd, &fspm_upd);
412 
413 	/* FSP disables the interrupt handler so remove debug exceptions temporarily  */
414 	null_breakpoint_disable();
415 	post_code(POSTCODE_FSP_MEMORY_INIT);
416 	timestamp_add_now(TS_FSP_MEMORY_INIT_START);
417 	if (ENV_X86_64 && CONFIG(PLATFORM_USES_FSP2_X86_32))
418 		status = protected_mode_call_2arg(fsp_raminit,
419 						  (uintptr_t)&fspm_upd,
420 						  (uintptr_t)fsp_get_hob_list_ptr());
421 	else
422 		status = fsp_raminit(&fspm_upd, fsp_get_hob_list_ptr());
423 	null_breakpoint_init();
424 
425 	post_code(POSTCODE_FSP_MEMORY_EXIT);
426 	timestamp_add_now(TS_FSP_MEMORY_INIT_END);
427 
428 	/* Handle any errors returned by FspMemoryInit */
429 	fspm_return_value_handler("FspMemoryInit", status, true);
430 
431 	if (CONFIG(PLATFORM_USES_FSP2_4))
432 		fspm_multi_phase_init(hdr);
433 
434 	do_fsp_post_memory_init(s3wake, version);
435 
436 	/*
437 	 * fsp_debug_after_memory_init() checks whether the end of the tolum
438 	 * region is the same as the top of cbmem, so must be called here
439 	 * after cbmem has been initialised in do_fsp_post_memory_init().
440 	 */
441 	fsp_debug_after_memory_init(status);
442 }
443 
fspm_allocator(void * arg,size_t size,const union cbfs_mdata * unused)444 static void *fspm_allocator(void *arg, size_t size, const union cbfs_mdata *unused)
445 {
446 	const struct fsp_load_descriptor *fspld = arg;
447 	struct fspm_context *context = fspld->arg;
448 	struct memranges *memmap = &context->memmap;
449 
450 	/* Non XIP FSP-M uses FSP-M address */
451 	uintptr_t fspm_begin = (uintptr_t)CONFIG_FSP_M_ADDR;
452 	uintptr_t fspm_end = fspm_begin + size;
453 
454 	if (check_region_overlap(memmap, "FSPM", fspm_begin, fspm_end) != CB_SUCCESS)
455 		return NULL;
456 
457 	return (void *)fspm_begin;
458 }
459 
preload_fspm(void)460 void preload_fspm(void)
461 {
462 	if (!CONFIG(CBFS_PRELOAD))
463 		return;
464 
465 	const char *fspm_cbfs = soc_select_fsp_m_cbfs();
466 	printk(BIOS_DEBUG, "Preloading %s\n", fspm_cbfs);
467 	cbfs_preload(fspm_cbfs);
468 }
469 
fsp_memory_init(bool s3wake)470 void fsp_memory_init(bool s3wake)
471 {
472 	struct range_entry prog_ranges[2];
473 	struct fspm_context context;
474 	const char *fspm_cbfs = soc_select_fsp_m_cbfs();
475 	struct fsp_load_descriptor fspld = {
476 		.fsp_prog = PROG_INIT(PROG_REFCODE, fspm_cbfs),
477 		.arg = &context,
478 	};
479 	struct fsp_header *hdr = &context.header;
480 	struct memranges *memmap = &context.memmap;
481 
482 	/* For FSP-M XIP we leave alloc NULL to get a direct mapping to flash. */
483 	if (!CONFIG(FSP_M_XIP))
484 		fspld.alloc = fspm_allocator;
485 
486 	elog_boot_notify(s3wake);
487 
488 	/* Build up memory map of romstage address space including CAR. */
489 	memranges_init_empty(memmap, &prog_ranges[0], ARRAY_SIZE(prog_ranges));
490 	if (ENV_CACHE_AS_RAM)
491 		memranges_insert(memmap, (uintptr_t)_car_region_start,
492 			_car_unallocated_start - _car_region_start, 0);
493 	memranges_insert(memmap, (uintptr_t)_program, REGION_SIZE(program), 0);
494 
495 	timestamp_add_now(TS_FSP_MEMORY_INIT_LOAD);
496 	if (fsp_load_component(&fspld, hdr) != CB_SUCCESS)
497 		die("FSPM not available or failed to load!\n");
498 
499 	if (CONFIG(FSP_M_XIP) && (uintptr_t)prog_start(&fspld.fsp_prog) != hdr->image_base)
500 		die("FSPM XIP base does not match: %p vs %p\n",
501 		    (void *)(uintptr_t)hdr->image_base, prog_start(&fspld.fsp_prog));
502 
503 	timestamp_add_now(TS_INITRAM_START);
504 
505 	do_fsp_memory_init(&context, s3wake);
506 
507 	timestamp_add_now(TS_INITRAM_END);
508 }
509