1;; @file 2; Provide FSP API entry points. 3; 4; Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> 5; This program and the accompanying materials 6; are licensed and made available under the terms and conditions of the BSD License 7; which accompanies this distribution. The full text of the license may be found at 8; http://opensource.org/licenses/bsd-license.php. 9; 10; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12;; 13 14 SECTION .text 15 16%include "SaveRestoreSseNasm.inc" 17%include "MicrocodeLoadNasm.inc" 18 19; 20; Following are fixed PCDs 21; 22extern ASM_PFX(PcdGet32 (PcdTemporaryRamBase)) 23extern ASM_PFX(PcdGet32 (PcdTemporaryRamSize)) 24extern ASM_PFX(PcdGet32 (PcdFspReservedBufferSize)) 25 26; 27; Following functions will be provided in PlatformSecLib 28; 29extern ASM_PFX(AsmGetFspBaseAddress) 30extern ASM_PFX(AsmGetFspInfoHeader) 31;extern ASM_PFX(LoadMicrocode) ; @todo: needs a weak implementation 32extern ASM_PFX(SecPlatformInit) ; @todo: needs a weak implementation 33extern ASM_PFX(SecCarInit) 34 35; 36; Define the data length that we saved on the stack top 37; 38DATA_LEN_OF_PER0 EQU 18h 39DATA_LEN_OF_MCUD EQU 18h 40DATA_LEN_AT_STACK_TOP EQU (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4) 41 42; 43; @todo: These structures are moved from MicrocodeLoadNasm.inc to avoid 44; build error. This needs to be fixed later on. 45; 46struc MicrocodeHdr 47 .MicrocodeHdrVersion: resd 1 48 .MicrocodeHdrRevision: resd 1 49 .MicrocodeHdrDate: resd 1 50 .MicrocodeHdrProcessor: resd 1 51 .MicrocodeHdrChecksum: resd 1 52 .MicrocodeHdrLoader: resd 1 53 .MicrocodeHdrFlags: resd 1 54 .MicrocodeHdrDataSize: resd 1 55 .MicrocodeHdrTotalSize: resd 1 56 .MicrocodeHdrRsvd: resd 3 57 .size: 58endstruc 59 60struc ExtSigHdr 61 .ExtSigHdrCount: resd 1 62 .ExtSigHdrChecksum: resd 1 63 .ExtSigHdrRsvd: resd 3 64 .size: 65endstruc 66 67struc ExtSig 68 .ExtSigProcessor: resd 1 69 .ExtSigFlags: resd 1 70 .ExtSigChecksum: resd 1 71 .size: 72endstruc 73 74struc LoadMicrocodeParams 75 ; FSP_UPD_HEADER { 76 .FspUpdHeader: resd 8 77 ; } 78 ; FSPT_CORE_UPD { 79 .MicrocodeCodeAddr: resd 1 80 .MicrocodeCodeSize: resd 1 81 .CodeRegionBase: resd 1 82 .CodeRegionSize: resd 1 83 ; } 84 .size: 85endstruc 86 87 88; 89; Define SSE macros 90; 91; 92;args 1: ReturnAddress 2:MmxRegister 93; 94%macro LOAD_MMX_EXT 2 95 mov esi, %1 96 movd %2, esi ; save ReturnAddress into MMX 97%endmacro 98 99; 100;args 1: RoutineLabel 2:MmxRegister 101; 102%macro CALL_MMX_EXT 2 103 mov esi, %%ReturnAddress 104 movd %2, esi ; save ReturnAddress into MMX 105 jmp %1 106%%ReturnAddress: 107%endmacro 108 109; 110;arg 1:MmxRegister 111; 112%macro RET_ESI_EXT 1 113 movd esi, %1 ; move ReturnAddress from MMX to ESI 114 jmp esi 115%endmacro 116 117; 118;arg 1:RoutineLabel 119; 120%macro CALL_MMX 1 121 CALL_MMX_EXT %1, mm7 122%endmacro 123 124%macro RET_ESI 0 125 RET_ESI_EXT mm7 126%endmacro 127 128; 129; @todo: The strong/weak implementation does not work. 130; This needs to be reviewed later. 131; 132;------------------------------------------------------------------------------ 133; 134;;global ASM_PFX(SecPlatformInitDefault) 135;ASM_PFX(SecPlatformInitDefault): 136; ; Inputs: 137; ; mm7 -> Return address 138; ; Outputs: 139; ; eax -> 0 - Successful, Non-zero - Failed. 140; ; Register Usage: 141; ; eax is cleared and ebp is used for return address. 142; ; All others reserved. 143; 144; ; Save return address to EBP 145; movd ebp, mm7 146; 147; xor eax, eax 148;Exit1: 149; jmp ebp 150 151;------------------------------------------------------------------------------ 152global ASM_PFX(LoadMicrocodeDefault) 153ASM_PFX(LoadMicrocodeDefault): 154 ; Inputs: 155 ; esp -> LoadMicrocodeParams pointer 156 ; Register Usage: 157 ; esp Preserved 158 ; All others destroyed 159 ; Assumptions: 160 ; No memory available, stack is hard-coded and used for return address 161 ; Executed by SBSP and NBSP 162 ; Beginning of microcode update region starts on paragraph boundary 163 164 ; 165 ; 166 ; Save return address to EBP 167 movd ebp, mm7 168 169 cmp esp, 0 170 jz ParamError 171 mov eax, dword [esp + 4] ; Parameter pointer 172 cmp eax, 0 173 jz ParamError 174 mov esp, eax 175 176 ; skip loading Microcode if the MicrocodeCodeSize is zero 177 ; and report error if size is less than 2k 178 mov eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize] 179 cmp eax, 0 180 jz Exit2 181 cmp eax, 0800h 182 jl ParamError 183 184 mov esi, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr] 185 cmp esi, 0 186 jnz CheckMainHeader 187 188ParamError: 189 mov eax, 080000002h 190 jmp Exit2 191 192CheckMainHeader: 193 ; Get processor signature and platform ID from the installed processor 194 ; and save into registers for later use 195 ; ebx = processor signature 196 ; edx = platform ID 197 mov eax, 1 198 cpuid 199 mov ebx, eax 200 mov ecx, MSR_IA32_PLATFORM_ID 201 rdmsr 202 mov ecx, edx 203 shr ecx, 50-32 ; shift (50d-32d=18d=0x12) bits 204 and ecx, 7h ; platform id at bit[52..50] 205 mov edx, 1 206 shl edx, cl 207 208 ; Current register usage 209 ; esp -> stack with parameters 210 ; esi -> microcode update to check 211 ; ebx = processor signature 212 ; edx = platform ID 213 214 ; Check for valid microcode header 215 ; Minimal test checking for header version and loader version as 1 216 mov eax, dword 1 217 cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], eax 218 jne AdvanceFixedSize 219 cmp dword [esi + MicrocodeHdr.MicrocodeHdrLoader], eax 220 jne AdvanceFixedSize 221 222 ; Check if signature and plaform ID match 223 cmp ebx, dword [esi + MicrocodeHdr.MicrocodeHdrProcessor] 224 jne LoadMicrocodeDefault1 225 test edx, dword [esi + MicrocodeHdr.MicrocodeHdrFlags ] 226 jnz LoadCheck ; Jif signature and platform ID match 227 228LoadMicrocodeDefault1: 229 ; Check if extended header exists 230 ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid 231 xor eax, eax 232 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax 233 je NextMicrocode 234 cmp dword [esi + MicrocodeHdr.MicrocodeHdrDataSize], eax 235 je NextMicrocode 236 237 ; Then verify total size - sizeof header > data size 238 mov ecx, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize] 239 sub ecx, MicrocodeHdr.size 240 cmp ecx, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize] 241 jng NextMicrocode ; Jif extended header does not exist 242 243 ; Set edi -> extended header 244 mov edi, esi 245 add edi, MicrocodeHdr.size 246 add edi, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize] 247 248 ; Get count of extended structures 249 mov ecx, dword [edi + ExtSigHdr.ExtSigHdrCount] 250 251 ; Move pointer to first signature structure 252 add edi, ExtSigHdr.size 253 254CheckExtSig: 255 ; Check if extended signature and platform ID match 256 cmp dword [edi + ExtSig.ExtSigProcessor], ebx 257 jne LoadMicrocodeDefault2 258 test dword [edi + ExtSig.ExtSigFlags], edx 259 jnz LoadCheck ; Jif signature and platform ID match 260LoadMicrocodeDefault2: 261 ; Check if any more extended signatures exist 262 add edi, ExtSig.size 263 loop CheckExtSig 264 265NextMicrocode: 266 ; Advance just after end of this microcode 267 xor eax, eax 268 cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax 269 je LoadMicrocodeDefault3 270 add esi, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize] 271 jmp CheckAddress 272LoadMicrocodeDefault3: 273 add esi, dword 2048 274 jmp CheckAddress 275 276AdvanceFixedSize: 277 ; Advance by 4X dwords 278 add esi, dword 1024 279 280CheckAddress: 281 ; Is valid Microcode start point ? 282 cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], 0ffffffffh 283 jz Done 284 285 ; Is automatic size detection ? 286 mov eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize] 287 cmp eax, 0ffffffffh 288 jz LoadMicrocodeDefault4 289 290 ; Address >= microcode region address + microcode region size? 291 add eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr] 292 cmp esi, eax 293 jae Done ;Jif address is outside of microcode region 294 jmp CheckMainHeader 295 296LoadMicrocodeDefault4: 297LoadCheck: 298 ; Get the revision of the current microcode update loaded 299 mov ecx, MSR_IA32_BIOS_SIGN_ID 300 xor eax, eax ; Clear EAX 301 xor edx, edx ; Clear EDX 302 wrmsr ; Load 0 to MSR at 8Bh 303 304 mov eax, 1 305 cpuid 306 mov ecx, MSR_IA32_BIOS_SIGN_ID 307 rdmsr ; Get current microcode signature 308 309 ; Verify this microcode update is not already loaded 310 cmp dword [esi + MicrocodeHdr.MicrocodeHdrRevision], edx 311 je Continue 312 313LoadMicrocode: 314 ; EAX contains the linear address of the start of the Update Data 315 ; EDX contains zero 316 ; ECX contains 79h (IA32_BIOS_UPDT_TRIG) 317 ; Start microcode load with wrmsr 318 mov eax, esi 319 add eax, MicrocodeHdr.size 320 xor edx, edx 321 mov ecx, MSR_IA32_BIOS_UPDT_TRIG 322 wrmsr 323 mov eax, 1 324 cpuid 325 326Continue: 327 jmp NextMicrocode 328 329Done: 330 mov eax, 1 331 cpuid 332 mov ecx, MSR_IA32_BIOS_SIGN_ID 333 rdmsr ; Get current microcode signature 334 xor eax, eax 335 cmp edx, 0 336 jnz Exit2 337 mov eax, 08000000Eh 338 339Exit2: 340 jmp ebp 341 342 343global ASM_PFX(EstablishStackFsp) 344ASM_PFX(EstablishStackFsp): 345 ; 346 ; Save parameter pointer in edx 347 ; 348 mov edx, dword [esp + 4] 349 350 ; 351 ; Enable FSP STACK 352 ; 353 mov esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))] 354 add esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))] 355 356 push DATA_LEN_OF_MCUD ; Size of the data region 357 push 4455434Dh ; Signature of the data region 'MCUD' 358 push dword [edx + 2Ch] ; Code size sizeof(FSPT_UPD_COMMON) + 12 359 push dword [edx + 28h] ; Code base sizeof(FSPT_UPD_COMMON) + 8 360 push dword [edx + 24h] ; Microcode size sizeof(FSPT_UPD_COMMON) + 4 361 push dword [edx + 20h] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0 362 363 ; 364 ; Save API entry/exit timestamp into stack 365 ; 366 push DATA_LEN_OF_PER0 ; Size of the data region 367 push 30524550h ; Signature of the data region 'PER0' 368 rdtsc 369 push edx 370 push eax 371 LOAD_EDX 372 push edx 373 LOAD_EAX 374 push eax 375 376 ; 377 ; Terminator for the data on stack 378 ; 379 push 0 380 381 ; 382 ; Set ECX/EDX to the BootLoader temporary memory range 383 ; 384 mov ecx, [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))] 385 mov edx, ecx 386 add edx, [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))] 387 sub edx, [ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))] 388 389 cmp ecx, edx ;If PcdFspReservedBufferSize >= PcdTemporaryRamSize, then error. 390 jb EstablishStackFspSuccess 391 mov eax, 80000003h ;EFI_UNSUPPORTED 392 jmp EstablishStackFspExit 393EstablishStackFspSuccess: 394 xor eax, eax 395 396EstablishStackFspExit: 397 RET_ESI 398 399;---------------------------------------------------------------------------- 400; TempRamInit API 401; 402; This FSP API will load the microcode update, enable code caching for the 403; region specified by the boot loader and also setup a temporary stack to be 404; used till main memory is initialized. 405; 406;---------------------------------------------------------------------------- 407global ASM_PFX(TempRamInitApi) 408ASM_PFX(TempRamInitApi): 409 ; 410 ; Ensure SSE is enabled 411 ; 412 ENABLE_SSE 413 414 ; 415 ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6 416 ; 417 SAVE_REGS 418 419 ; 420 ; Save timestamp into XMM6 421 ; 422 rdtsc 423 SAVE_EAX 424 SAVE_EDX 425 426 ; 427 ; Check Parameter 428 ; 429 mov eax, dword [esp + 4] 430 cmp eax, 0 431 mov eax, 80000002h 432 jz TempRamInitExit 433 434 ; 435 ; Sec Platform Init 436 ; 437 CALL_MMX ASM_PFX(SecPlatformInit) 438 cmp eax, 0 439 jnz TempRamInitExit 440 441 ; Load microcode 442 LOAD_ESP 443 CALL_MMX ASM_PFX(LoadMicrocodeDefault) 444 SXMMN xmm6, 3, eax ;Save microcode return status in ECX-SLOT 3 in xmm6. 445 ;@note If return value eax is not 0, microcode did not load, but continue and attempt to boot. 446 447 ; Call Sec CAR Init 448 LOAD_ESP 449 CALL_MMX ASM_PFX(SecCarInit) 450 cmp eax, 0 451 jnz TempRamInitExit 452 453 LOAD_ESP 454 CALL_MMX ASM_PFX(EstablishStackFsp) 455 cmp eax, 0 456 jnz TempRamInitExit 457 458 LXMMN xmm6, eax, 3 ;Restore microcode status if no CAR init error from ECX-SLOT 3 in xmm6. 459 460TempRamInitExit: 461 mov bl, al ; save al data in bl 462 mov al, 07Fh ; API exit postcode 7f 463 out 080h, al 464 mov al, bl ; restore al data from bl 465 466 ; 467 ; Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6 468 ; 469 LOAD_REGS 470 ret 471 472;---------------------------------------------------------------------------- 473; Module Entrypoint API 474;---------------------------------------------------------------------------- 475global ASM_PFX(_ModuleEntryPoint) 476ASM_PFX(_ModuleEntryPoint): 477 jmp $ 478