1;------------------------------------------------------------------------------
2;
3; Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
4; SPDX-License-Identifier: BSD-2-Clause-Patent
5;
6; Module Name:
7;
8;  SecEntry.asm
9;
10; Abstract:
11;
12;  This is the code that goes from real-mode to protected mode.
13;  It consumes the reset vector, calls TempRamInit API from FSP binary.
14;
15;------------------------------------------------------------------------------
16
17#include "Fsp.h"
18
19.686p
20.xmm
21.model small, c
22
23EXTRN   CallPeiCoreEntryPoint:NEAR
24EXTRN   TempRamInitParams:FAR
25
26; Pcds
27EXTRN   PcdGet32 (PcdFlashFvFspBase):DWORD
28EXTRN   PcdGet32 (PcdFlashFvFspSize):DWORD
29
30_TEXT_REALMODE      SEGMENT PARA PUBLIC USE16 'CODE'
31                    ASSUME  CS:_TEXT_REALMODE, DS:_TEXT_REALMODE
32
33;----------------------------------------------------------------------------
34;
35; Procedure:    _ModuleEntryPoint
36;
37; Input:        None
38;
39; Output:       None
40;
41; Destroys:     Assume all registers
42;
43; Description:
44;
45;   Transition to non-paged flat-model protected mode from a
46;   hard-coded GDT that provides exactly two descriptors.
47;   This is a bare bones transition to protected mode only
48;   used for a while in PEI and possibly DXE.
49;
50;   After enabling protected mode, a far jump is executed to
51;   transfer to PEI using the newly loaded GDT.
52;
53; Return:       None
54;
55;  MMX Usage:
56;              MM0 = BIST State
57;              MM5 = Save time-stamp counter value high32bit
58;              MM6 = Save time-stamp counter value low32bit.
59;
60;----------------------------------------------------------------------------
61
62align 4
63_ModuleEntryPoint PROC NEAR C PUBLIC
64  fninit                                ; clear any pending Floating point exceptions
65  ;
66  ; Store the BIST value in mm0
67  ;
68  movd    mm0, eax
69
70  ;
71  ; Save time-stamp counter value
72  ; rdtsc load 64bit time-stamp counter to EDX:EAX
73  ;
74  rdtsc
75  movd    mm5, edx
76  movd    mm6, eax
77
78  ;
79  ; Load the GDT table in GdtDesc
80  ;
81  mov     esi,  OFFSET GdtDesc
82  DB      66h
83  lgdt    fword ptr cs:[si]
84
85  ;
86  ; Transition to 16 bit protected mode
87  ;
88  mov     eax, cr0                   ; Get control register 0
89  or      eax, 00000003h             ; Set PE bit (bit #0) & MP bit (bit #1)
90  mov     cr0, eax                   ; Activate protected mode
91
92  mov     eax, cr4                   ; Get control register 4
93  or      eax, 00000600h             ; Set OSFXSR bit (bit #9) & OSXMMEXCPT bit (bit #10)
94  mov     cr4, eax
95
96  ;
97  ; Now we're in 16 bit protected mode
98  ; Set up the selectors for 32 bit protected mode entry
99  ;
100  mov     ax, SYS_DATA_SEL
101  mov     ds, ax
102  mov     es, ax
103  mov     fs, ax
104  mov     gs, ax
105  mov     ss, ax
106
107  ;
108  ; Transition to Flat 32 bit protected mode
109  ; The jump to a far pointer causes the transition to 32 bit mode
110  ;
111  mov esi, offset ProtectedModeEntryLinearAddress
112  jmp     fword ptr cs:[si]
113
114_ModuleEntryPoint   ENDP
115_TEXT_REALMODE      ENDS
116
117_TEXT_PROTECTED_MODE      SEGMENT PARA PUBLIC USE32 'CODE'
118                          ASSUME  CS:_TEXT_PROTECTED_MODE, DS:_TEXT_PROTECTED_MODE
119
120;----------------------------------------------------------------------------
121;
122; Procedure:    ProtectedModeEntryPoint
123;
124; Input:        None
125;
126; Output:       None
127;
128; Destroys:     Assume all registers
129;
130; Description:
131;
132; This function handles:
133;   Call two basic APIs from FSP binary
134;   Initializes stack with some early data (BIST, PEI entry, etc)
135;
136; Return:       None
137;
138;----------------------------------------------------------------------------
139
140align 4
141ProtectedModeEntryPoint PROC NEAR PUBLIC
142
143  ; Find the fsp info header
144  mov  edi, PcdGet32 (PcdFlashFvFspBase)
145  mov  ecx, PcdGet32 (PcdFlashFvFspSize)
146
147  mov  eax, dword ptr [edi + FVH_SIGINATURE_OFFSET]
148  cmp  eax, FVH_SIGINATURE_VALID_VALUE
149  jnz  FspHeaderNotFound
150
151  xor  eax, eax
152  mov  ax, word ptr [edi + FVH_EXTHEADER_OFFSET_OFFSET]
153  cmp  ax, 0
154  jnz  FspFvExtHeaderExist
155
156  xor  eax, eax
157  mov  ax, word ptr [edi + FVH_HEADER_LENGTH_OFFSET]   ; Bypass Fv Header
158  add  edi, eax
159  jmp  FspCheckFfsHeader
160
161FspFvExtHeaderExist:
162  add  edi, eax
163  mov  eax, dword ptr [edi + FVH_EXTHEADER_SIZE_OFFSET]  ; Bypass Ext Fv Header
164  add  edi, eax
165
166  ; Round up to 8 byte alignment
167  mov  eax, edi
168  and  al,  07h
169  jz FspCheckFfsHeader
170
171  and  edi, 0FFFFFFF8h
172  add  edi, 08h
173
174FspCheckFfsHeader:
175  ; Check the ffs guid
176  mov  eax, dword ptr [edi]
177  cmp  eax, FSP_HEADER_GUID_DWORD1
178  jnz FspHeaderNotFound
179
180  mov  eax, dword ptr [edi + 4]
181  cmp  eax, FSP_HEADER_GUID_DWORD2
182  jnz FspHeaderNotFound
183
184  mov  eax, dword ptr [edi + 8]
185  cmp  eax, FSP_HEADER_GUID_DWORD3
186  jnz FspHeaderNotFound
187
188  mov  eax, dword ptr [edi + 0Ch]
189  cmp  eax, FSP_HEADER_GUID_DWORD4
190  jnz FspHeaderNotFound
191
192  add  edi, FFS_HEADER_SIZE_VALUE       ; Bypass the ffs header
193
194  ; Check the section type as raw section
195  mov  al, byte ptr [edi + SECTION_HEADER_TYPE_OFFSET]
196  cmp  al, 019h
197  jnz FspHeaderNotFound
198
199  add  edi, RAW_SECTION_HEADER_SIZE_VALUE ; Bypass the section header
200  jmp FspHeaderFound
201
202FspHeaderNotFound:
203  jmp  $
204
205FspHeaderFound:
206  ; Get the fsp TempRamInit Api address
207  mov eax, dword ptr [edi + FSP_HEADER_IMAGEBASE_OFFSET]
208  add eax, dword ptr [edi + FSP_HEADER_TEMPRAMINIT_OFFSET]
209
210  ; Setup the hardcode stack
211  mov esp, OFFSET TempRamInitStack
212
213  ; Call the fsp TempRamInit Api
214  jmp eax
215
216TempRamInitDone:
217  cmp eax, 8000000Eh      ;Check if EFI_NOT_FOUND returned. Error code for Microcode Update not found.
218  je  CallSecFspInit      ;If microcode not found, don't hang, but continue.
219
220  cmp eax, 0              ;Check if EFI_SUCCESS retuned.
221  jnz FspApiFailed
222
223  ;   ECX: start of range
224  ;   EDX: end of range
225CallSecFspInit:
226  xor     eax, eax
227  mov     esp, edx
228
229  ; Align the stack at DWORD
230  add  esp,  3
231  and  esp, 0FFFFFFFCh
232
233  push    edx
234  push    ecx
235  push    eax ; zero - no hob list yet
236  call CallPeiCoreEntryPoint
237
238FspApiFailed:
239  jmp $
240
241align 10h
242TempRamInitStack:
243    DD  OFFSET TempRamInitDone
244    DD  OFFSET TempRamInitParams
245
246ProtectedModeEntryPoint ENDP
247
248;
249; ROM-based Global-Descriptor Table for the Tiano PEI Phase
250;
251align 16
252PUBLIC  BootGdtTable
253
254;
255; GDT[0]: 0x00: Null entry, never used.
256;
257NULL_SEL            EQU $ - GDT_BASE    ; Selector [0]
258GDT_BASE:
259BootGdtTable        DD  0
260                    DD  0
261;
262; Linear data segment descriptor
263;
264LINEAR_SEL          EQU $ - GDT_BASE    ; Selector [0x8]
265    DW  0FFFFh                          ; limit 0xFFFFF
266    DW  0                               ; base 0
267    DB  0
268    DB  092h                            ; present, ring 0, data, expand-up, writable
269    DB  0CFh                            ; page-granular, 32-bit
270    DB  0
271;
272; Linear code segment descriptor
273;
274LINEAR_CODE_SEL     EQU $ - GDT_BASE    ; Selector [0x10]
275    DW  0FFFFh                          ; limit 0xFFFFF
276    DW  0                               ; base 0
277    DB  0
278    DB  09Bh                            ; present, ring 0, data, expand-up, not-writable
279    DB  0CFh                            ; page-granular, 32-bit
280    DB  0
281;
282; System data segment descriptor
283;
284SYS_DATA_SEL        EQU $ - GDT_BASE    ; Selector [0x18]
285    DW  0FFFFh                          ; limit 0xFFFFF
286    DW  0                               ; base 0
287    DB  0
288    DB  093h                            ; present, ring 0, data, expand-up, not-writable
289    DB  0CFh                            ; page-granular, 32-bit
290    DB  0
291
292;
293; System code segment descriptor
294;
295SYS_CODE_SEL        EQU $ - GDT_BASE    ; Selector [0x20]
296    DW  0FFFFh                          ; limit 0xFFFFF
297    DW  0                               ; base 0
298    DB  0
299    DB  09Ah                            ; present, ring 0, data, expand-up, writable
300    DB  0CFh                            ; page-granular, 32-bit
301    DB  0
302;
303; Spare segment descriptor
304;
305SYS16_CODE_SEL      EQU $ - GDT_BASE    ; Selector [0x28]
306    DW  0FFFFh                          ; limit 0xFFFFF
307    DW  0                               ; base 0
308    DB  0Eh                             ; Changed from F000 to E000.
309    DB  09Bh                            ; present, ring 0, code, expand-up, writable
310    DB  00h                             ; byte-granular, 16-bit
311    DB  0
312;
313; Spare segment descriptor
314;
315SYS16_DATA_SEL      EQU $ - GDT_BASE    ; Selector [0x30]
316    DW  0FFFFh                          ; limit 0xFFFF
317    DW  0                               ; base 0
318    DB  0
319    DB  093h                            ; present, ring 0, data, expand-up, not-writable
320    DB  00h                             ; byte-granular, 16-bit
321    DB  0
322
323;
324; Spare segment descriptor
325;
326SPARE5_SEL          EQU $ - GDT_BASE    ; Selector [0x38]
327    DW  0                               ; limit 0
328    DW  0                               ; base 0
329    DB  0
330    DB  0                               ; present, ring 0, data, expand-up, writable
331    DB  0                               ; page-granular, 32-bit
332    DB  0
333GDT_SIZE            EQU $ - BootGdtTable    ; Size, in bytes
334
335;
336; GDT Descriptor
337;
338GdtDesc:                                ; GDT descriptor
339    DW  GDT_SIZE - 1                    ; GDT limit
340    DD  OFFSET BootGdtTable             ; GDT base address
341
342
343ProtectedModeEntryLinearAddress   LABEL   FWORD
344ProtectedModeEntryLinearOffset    LABEL   DWORD
345  DD      OFFSET ProtectedModeEntryPoint  ; Offset of our 32 bit code
346  DW      LINEAR_CODE_SEL
347
348_TEXT_PROTECTED_MODE    ENDS
349END
350