/ src / cpu / intel / car / romstage.c
romstage.c
 1  /* SPDX-License-Identifier: GPL-2.0-only */
 2  
 3  #include <adainit.h>
 4  #include <arch/romstage.h>
 5  #include <arch/symbols.h>
 6  #include <arch/stack_canary_breakpoint.h>
 7  #include <commonlib/helpers.h>
 8  #include <console/console.h>
 9  #include <cpu/x86/smm.h>
10  #include <program_loading.h>
11  #include <romstage_common.h>
12  #include <security/vboot/vboot_common.h>
13  #include <types.h>
14  
15  /* If we do not have a constrained _car_stack region size, use the
16     following as a guideline for acceptable stack usage. */
17  #define DCACHE_RAM_ROMSTAGE_STACK_SIZE 0x2000
18  
19  void __noreturn romstage_main(void)
20  {
21  	int i;
22  	const int num_guards = 64;
23  	const u32 stack_guard = 0xdeadbeef;
24  	u32 *stack_base;
25  	u32 size;
26  	const size_t stack_size = MAX(CONFIG_DCACHE_BSP_STACK_SIZE,
27  				      DCACHE_RAM_ROMSTAGE_STACK_SIZE);
28  
29  	/* Size of unallocated CAR. */
30  	size = ALIGN_DOWN(_car_stack_size, 16);
31  
32  	size = MIN(size, stack_size);
33  	if (size < stack_size)
34  		printk(BIOS_DEBUG, "Romstage stack size limited to 0x%x!\n",
35  			size);
36  
37  	stack_base = (u32 *)(_ecar_stack - size);
38  
39  	/* Disable breakpoint since stack is intentionally corrupted */
40  	stack_canary_breakpoint_remove();
41  
42  	/*
43  	 * The "stack guard" and the "stack canary breakpoint" can both detect excessive
44  	 * stack usage. Excessive stack usage can corrupt data and lead to undefined
45  	 * (and thus hard to debug) behaviour.
46  	 * The stack guard will be checked later on, assuming the corruption wasn't to
47  	 * severe and allowed romstage to run. It's useful to detect problems when
48  	 * HW breakpoints were disabled.
49  	 *
50  	 * When HW breakpoints are used and enabled, the stack canary breakpoint will
51  	 * report the instruction pointer immediately, which can hint at which function
52  	 * may be using too much stack. FSP might disable HW breakpoints, though.
53  	 */
54  	for (i = 0; i < num_guards; i++)
55  		stack_base[i] = stack_guard;
56  
57  	stack_canary_breakpoint_init();
58  
59  	if (CONFIG(VBOOT_EARLY_EC_SYNC))
60  		vboot_sync_ec();
61  
62  	/*
63  	 * We can generally jump between C and Ada code back and forth
64  	 * without trouble. But since we don't have an Ada main() we
65  	 * have to do some Ada package initializations that GNAT would
66  	 * do there. This has to be done before calling any Ada code.
67  	 *
68  	 * The package initializations should not have any dependen-
69  	 * cies on C code. So we can call them here early, and don't
70  	 * have to worry at which point we can start to use Ada.
71  	 */
72  	romstage_adainit();
73  
74  	mainboard_romstage_entry();
75  
76  	/* Check the stack. */
77  	for (i = 0; i < num_guards; i++) {
78  		if (stack_base[i] == stack_guard)
79  			continue;
80  		printk(BIOS_DEBUG, "Smashed stack detected in romstage!\n");
81  	}
82  
83  	if (CONFIG(SMM_TSEG))
84  		smm_list_regions();
85  
86  	prepare_and_run_postcar();
87  	/* We do not return here. */
88  }