• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <cpu/x86/mtrr.h>
4#include <cpu/x86/cache.h>
5#include <cpu/x86/post_code.h>
6
7/*
8 * Replacement for cache_as_ram.inc when using the FSP binary.  This code
9 * locates the FSP binary, initializes the cache as RAM and performs the
10 * first stage of initialization.  Next this code switches the stack from
11 * the cache to RAM and then disables the cache as RAM.  Finally this code
12 * performs the final stage of initialization.
13 */
14
15#define LHLT_DELAY	0x50000	/* I/O delay between post codes on failure */
16
17.section .init, "ax", @progbits
18
19.global	bootblock_pre_c_entry
20bootblock_pre_c_entry:
21	/*
22	 * Per FSP1.1 specs, following registers are preserved:
23	 * EBX, EDI, ESI, EBP, MM0, MM1
24	 *
25	 * Shift values to release MM2.
26	 * mm0 -> ebx:  BIST value
27	 * mm1 -> mm0:  low 32-bits of TSC value
28	 * mm2 -> mm1:  high 32-bits of TSC value
29	 */
30	movd	%mm0, %ebx
31	movd	%mm1, %eax
32	movd	%eax, %mm0
33	movd	%mm2, %eax
34	movd	%eax, %mm1
35
36cache_as_ram:
37	post_code(POSTCODE_BOOTBLOCK_CAR)
38
39	/* Cache the rom and update the microcode */
40cache_rom:
41	/* Disable cache */
42	movl	%cr0, %eax
43	orl	$CR0_CacheDisable, %eax
44	movl	%eax, %cr0
45
46	movl	$MTRR_PHYS_BASE(1), %ecx
47	xorl	%edx, %edx
48	movl	$(CACHE_ROM_BASE | MTRR_TYPE_WRPROT), %eax
49	wrmsr
50
51	movl	$MTRR_PHYS_MASK(1), %ecx
52	rdmsr
53	movl	$(~(CACHE_ROM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax
54	wrmsr
55
56	/* Enable cache */
57	movl	%cr0, %eax
58	andl	$(~(CR0_CacheDisable | CR0_NoWriteThrough)), %eax
59	invd
60	movl	%eax, %cr0
61
62	/* Enable MTRR. */
63	movl	$MTRR_DEF_TYPE_MSR, %ecx
64	rdmsr
65	orl	$MTRR_DEF_TYPE_EN, %eax
66	wrmsr
67
68	/* The Google FSP release for Braswell has broken microcode update
69	   code and FSP needs the installed microcode revision to be non zero.
70	   It is better to have coreboot do it instead of relying on a fragile
71	   blob. */
72update_microcode:
73	/* put the return address in %esp */
74	movl	$end_microcode_update, %esp
75	jmp	update_bsp_microcode
76end_microcode_update:
77
78	/*
79	 * Find the FSP binary in cbfs.
80	 * Make a fake stack that has the return value back to this code.
81	 */
82	lea	fake_fsp_stack, %esp
83	jmp	find_fsp
84find_fsp_ret:
85	/* Save the FSP location */
86	mov	%eax, %ebp
87
88	/*
89	 * Only when a valid FSP binary is found at CONFIG_FSP_LOC is
90	 * the returned FSP_INFO_HEADER structure address above the base
91	 * address of FSP binary specified by the CONFIG_FSP_LOC value.
92	 * All of the error values are in the 0x8xxxxxxx range which are
93	 * below the CONFIG_FSP_LOC value.
94	 */
95	cmp	$CONFIG_FSP_LOC, %eax
96	jbe	halt1
97
98	post_code(POSTCODE_FSP_TEMP_RAM_INIT)
99
100	/* Calculate entry into FSP */
101	mov	0x30(%ebp), %eax	/* Load TempRamInitEntry */
102	add	0x1c(%ebp), %eax	/* add in the offset for FSP */
103
104	/*
105	 * Pass early init variables on a fake stack (no memory yet)
106	 * as well as the return location
107	 */
108	lea	CAR_init_stack, %esp
109
110	/*
111	 *       BIST value is zero
112	 * eax:  TempRamInitApi address
113	 * ebx:  BIST value
114	 * ebp:  FSP_INFO_HEADER address
115	 * esi:  Not used
116	 * mm0:  low 32-bits of TSC value
117	 * mm1:  high 32-bits of TSC value
118	 */
119
120	/* call FSP binary to setup temporary stack */
121	jmp	*%eax
122
123CAR_init_done:
124
125	/*
126	 * ebp:  FSP_INFO_HEADER address
127	 * ebx:  BIST value
128	 * ecx:  Temp RAM base
129	 * edx:  Temp RAM top
130	 * mm0:  low 32-bits of TSC value
131	 * mm1:  high 32-bits of TSC value
132	 */
133
134	cmp	$0, %eax
135	jne	halt2
136
137	/* Setup bootblock stack */
138	movl	$_ecar_stack, %esp
139
140	/*
141	 * ebp:  FSP_INFO_HEADER address
142	 * ebx:  BIST value
143	 * ecx:  Temp RAM base
144	 * edx:  Temp RAM top
145	 * esp:  Top of stack in temp RAM
146	 * mm0:  low 32-bits of TSC value
147	 * mm1:  high 32-bits of TSC value
148	 */
149
150	/*
151	 * temp_memory_start/end reside in the .bss section, which gets cleared
152	 * below. Save the FSP return value to the stack before writing those
153	 * variables.
154	 */
155	push	%ecx
156	push	%edx
157
158	/* clear .bss section */
159	cld
160	xor	%eax, %eax
161	movl	$(_ebss), %ecx
162	movl	$(_bss), %edi
163	sub	%edi, %ecx
164	shrl	$2, %ecx
165	rep	stosl
166
167	pop	%edx
168	movl	%edx, temp_memory_end
169	pop	%ecx
170	movl	%ecx, temp_memory_start
171
172	/* Need to align stack to 16 bytes at call instruction. Account for
173	the pushes below. */
174	andl	$0xfffffff0, %esp
175	subl	$8, %esp
176
177	/* Push initial timestamp on the stack */
178	movd	%mm1, %eax
179	pushl	%eax	/* tsc[63:32] */
180	movd	%mm0, %eax
181	pushl	%eax	/* tsc[31:0] */
182
183	/* Copy .data section content to Cache-As-Ram */
184#include <cpu/x86/copy_data_section.inc>
185
186before_romstage:
187	/* Call bootblock_c_entry(uint64_t base_timestamp) */
188	call	bootblock_c_entry
189
190	/* Never reached */
191
192halt1:
193	/*
194	 * Failures for postcode 0xBA - failed in fsp_fih_early_find()
195	 *
196	 * Values are:
197	 * 0x01 - FV signature, "_FVH" not present
198	 * 0x02 - FFS GUID not present
199	 * 0x03 - FSP INFO Header not found
200	 * 0x04 - ImageBase does not equal CONFIG_FSP_LOC - Is the FSP rebased
201	 *	  to a different location, or does it need to be?
202	 * 0x05 - FSP INFO Header signature "FSPH" not found
203	 * 0x06 - FSP Image ID is not the expected ID.
204	 */
205	movb	$0xBA, %ah
206	jmp	.Lhlt
207
208halt2:
209	/*
210	 * Failures for postcode 0xBB - failed in the FSP:
211	 *
212	 * 0x00 - FSP_SUCCESS: Temp RAM was initialized successfully.
213	 * 0x02 - FSP_INVALID_PARAMETER: Input parameters are invalid.
214	 * 0x03 - FSP_UNSUPPORTED: The FSP calling conditions were not met.
215	 * 0x07 - FSP_DEVICE_ERROR: Temp RAM initialization failed
216	 * 0x0E - FSP_NOT_FOUND: No valid microcode was found in the microcode
217	 *	  region.
218	 * 0x14 - FSP_ALREADY_STARTED: Temp RAM initialization has been invoked
219	 */
220	movb	$0xBB, %ah
221	jmp	.Lhlt
222
223.Lhlt:
224	xchg	%al, %ah
225#if CONFIG(POST_IO)
226	outb	%al, $CONFIG_POST_IO_PORT
227#else
228	post_code(POSTCODE_DEAD_CODE)
229#endif
230	movl	$LHLT_DELAY, %ecx
231.Lhlt_Delay:
232	outb	%al, $0xED
233	loop	.Lhlt_Delay
234	jmp	.Lhlt
235
236/*
237 * esp is set to this location so that the call into and return from the FSP
238 * in find_fsp will work.
239 */
240	.align 4
241fake_fsp_stack:
242	.long	find_fsp_ret
243	.long	CONFIG_FSP_LOC		/* FSP base address */
244
245CAR_init_params:
246	.long	fake_microcode				/* Microcode Location */
247	.long	fake_microcode_end - fake_microcode	/* Microcode Length */
248	.long	0xFFFFFFFF - CONFIG_ROM_SIZE + 1	/* Firmware Location */
249	.long	CONFIG_ROM_SIZE				/* Firmware Length */
250
251CAR_init_stack:
252	.long	CAR_init_done
253	.long	CAR_init_params
254
255	/* coreboot updates microcode itself. FSP still needs a pointer
256	   to something that looks like microcode, so provide it with fake
257	   microcode. */
258fake_microcode:
259fake_microcode_header_start:
260	.long	1		/* Header Version */
261	.long	1		/* Microcode revision */
262	.long	0x10232019	/* Date: Time of writing 23-10-2019 */
263	.long	0x00010ff0	/* Sig: (non existing) Family: 0xf, Model: 0x1f, stepping: 0 */
264	.long	0		/* Checksum: not checked by FSP, so won't care */
265	.long	1		/* Loader Revision */
266	.long	1		/* Processor Flags */
267	.long	fake_microcode_end - fake_microcode_header_end	/* Data Size */
268	.long	fake_microcode_end - fake_microcode	/* Total Size */
269	.space	12		/* Reserved */
270fake_microcode_header_end:
271	.space 0x10	/* 16 bytes of empty data */
272fake_microcode_end:
273