1 ;------------------------------------------------------------------------------
3 ; Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
4 ; SPDX-License-Identifier: BSD-2-Clause-Patent
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.
15 ;------------------------------------------------------------------------------
21 extern ASM_PFX(CallPeiCoreEntryPoint)
22 extern ASM_PFX(FsptUpdDataPtr)
25 extern ASM_PFX(PcdGet32 (PcdFsptBaseAddress))
27 ;----------------------------------------------------------------------------
29 ; Procedure: _ModuleEntryPoint
35 ; Destroys: Assume all registers
39 ; Transition to non-paged flat-model protected mode from a
40 ; hard-coded GDT that provides exactly two descriptors.
41 ; This is a bare bones transition to protected mode only
42 ; used for a while in PEI and possibly DXE.
44 ; After enabling protected mode, a far jump is executed to
45 ; transfer to PEI using the newly loaded GDT.
51 ; MM5 = Save time-stamp counter value high32bit
52 ; MM6 = Save time-stamp counter value low32bit.
54 ;----------------------------------------------------------------------------
58 global ASM_PFX(ModuleEntryPoint)
59 ASM_PFX(ModuleEntryPoint):
60 fninit ; clear any pending Floating point exceptions
62 ; Store the BIST value in mm0
67 ; Save time-stamp counter value
68 ; rdtsc load 64bit time-stamp counter to EDX:EAX
75 ; Load the GDT table in GdtDesc
82 ; Transition to 16 bit protected mode
84 mov eax, cr0 ; Get control register 0
85 or eax, 00000003h ; Set PE bit (bit #0) & MP bit (bit #1)
86 mov cr0, eax ; Activate protected mode
88 mov eax, cr4 ; Get control register 4
89 or eax, 00000600h ; Set OSFXSR bit (bit #9) & OSXMMEXCPT bit (bit #10)
93 ; Now we're in 16 bit protected mode
94 ; Set up the selectors for 32 bit protected mode entry
104 ; Transition to Flat 32 bit protected mode
105 ; The jump to a far pointer causes the transition to 32 bit mode
107 mov esi, ProtectedModeEntryLinearAddress
108 jmp dword far [cs:si]
110 ;----------------------------------------------------------------------------
112 ; Procedure: ProtectedModeEntryPoint
118 ; Destroys: Assume all registers
122 ; This function handles:
123 ; Call two basic APIs from FSP binary
124 ; Initializes stack with some early data (BIST, PEI entry, etc)
128 ;----------------------------------------------------------------------------
132 ProtectedModeEntryPoint:
134 ; Find the fsp info header
135 mov edi, [ASM_PFX(PcdGet32 (PcdFsptBaseAddress))]
137 mov eax, dword [edi + FVH_SIGINATURE_OFFSET]
138 cmp eax, FVH_SIGINATURE_VALID_VALUE
139 jnz FspHeaderNotFound
142 mov ax, word [edi + FVH_EXTHEADER_OFFSET_OFFSET]
144 jnz FspFvExtHeaderExist
147 mov ax, word [edi + FVH_HEADER_LENGTH_OFFSET] ; Bypass Fv Header
149 jmp FspCheckFfsHeader
153 mov eax, dword [edi + FVH_EXTHEADER_SIZE_OFFSET] ; Bypass Ext Fv Header
156 ; Round up to 8 byte alignment
167 cmp eax, FSP_HEADER_GUID_DWORD1
168 jnz FspHeaderNotFound
170 mov eax, dword [edi + 4]
171 cmp eax, FSP_HEADER_GUID_DWORD2
172 jnz FspHeaderNotFound
174 mov eax, dword [edi + 8]
175 cmp eax, FSP_HEADER_GUID_DWORD3
176 jnz FspHeaderNotFound
178 mov eax, dword [edi + 0Ch]
179 cmp eax, FSP_HEADER_GUID_DWORD4
180 jnz FspHeaderNotFound
182 add edi, FFS_HEADER_SIZE_VALUE ; Bypass the ffs header
184 ; Check the section type as raw section
185 mov al, byte [edi + SECTION_HEADER_TYPE_OFFSET]
187 jnz FspHeaderNotFound
189 add edi, RAW_SECTION_HEADER_SIZE_VALUE ; Bypass the section header
196 ; Get the fsp TempRamInit Api address
197 mov eax, dword [edi + FSP_HEADER_IMAGEBASE_OFFSET]
198 add eax, dword [edi + FSP_HEADER_TEMPRAMINIT_OFFSET]
200 ; Setup the hardcode stack
201 mov esp, TempRamInitStack
203 ; Call the fsp TempRamInit Api
207 cmp eax, 8000000Eh ;Check if EFI_NOT_FOUND returned. Error code for Microcode Update not found.
208 je CallSecFspInit ;If microcode not found, don't hang, but continue.
210 cmp eax, 0 ;Check if EFI_SUCCESS returned.
213 ; ECX: start of range
219 ; Align the stack at DWORD
225 push eax ; zero - no hob list yet
226 call ASM_PFX(CallPeiCoreEntryPoint)
234 DD ASM_PFX(FsptUpdDataPtr); TempRamInitParams
237 ; ROM-based Global-Descriptor Table for the Tiano PEI Phase
240 global ASM_PFX(BootGdtTable)
243 ; GDT[0]: 0x00: Null entry, never used.
245 NULL_SEL EQU $ - GDT_BASE ; Selector [0]
247 ASM_PFX(BootGdtTable):
251 ; Linear data segment descriptor
253 LINEAR_SEL EQU $ - GDT_BASE ; Selector [0x8]
254 DW 0FFFFh ; limit 0xFFFFF
257 DB 092h ; present, ring 0, data, expand-up, writable
258 DB 0CFh ; page-granular, 32-bit
261 ; Linear code segment descriptor
263 LINEAR_CODE_SEL EQU $ - GDT_BASE ; Selector [0x10]
264 DW 0FFFFh ; limit 0xFFFFF
267 DB 09Bh ; present, ring 0, data, expand-up, not-writable
268 DB 0CFh ; page-granular, 32-bit
271 ; System data segment descriptor
273 SYS_DATA_SEL EQU $ - GDT_BASE ; Selector [0x18]
274 DW 0FFFFh ; limit 0xFFFFF
277 DB 093h ; present, ring 0, data, expand-up, not-writable
278 DB 0CFh ; page-granular, 32-bit
282 ; System code segment descriptor
284 SYS_CODE_SEL EQU $ - GDT_BASE ; Selector [0x20]
285 DW 0FFFFh ; limit 0xFFFFF
288 DB 09Ah ; present, ring 0, data, expand-up, writable
289 DB 0CFh ; page-granular, 32-bit
292 ; Spare segment descriptor
294 SYS16_CODE_SEL EQU $ - GDT_BASE ; Selector [0x28]
295 DW 0FFFFh ; limit 0xFFFFF
297 DB 0Eh ; Changed from F000 to E000.
298 DB 09Bh ; present, ring 0, code, expand-up, writable
299 DB 00h ; byte-granular, 16-bit
302 ; Spare segment descriptor
304 SYS16_DATA_SEL EQU $ - GDT_BASE ; Selector [0x30]
305 DW 0FFFFh ; limit 0xFFFF
308 DB 093h ; present, ring 0, data, expand-up, not-writable
309 DB 00h ; byte-granular, 16-bit
313 ; Spare segment descriptor
315 SPARE5_SEL EQU $ - GDT_BASE ; Selector [0x38]
319 DB 0 ; present, ring 0, data, expand-up, writable
320 DB 0 ; page-granular, 32-bit
322 GDT_SIZE EQU $ - GDT_BASE ; Size, in bytes
327 GdtDesc: ; GDT descriptor
328 DW GDT_SIZE - 1 ; GDT limit
329 DD GDT_BASE ; GDT base address
332 ProtectedModeEntryLinearAddress:
333 ProtectedModeEntryLinear:
334 DD ProtectedModeEntryPoint ; Offset of our 32 bit code