• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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