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