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