;------------------------------------------------------------------------------ | |
; | |
; Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> | |
; This program and the accompanying materials | |
; are licensed and made available under the terms and conditions of the BSD License | |
; which accompanies this distribution. The full text of the license may be found at | |
; http://opensource.org/licenses/bsd-license.php. | |
; | |
; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
; | |
; Module Name: | |
; | |
; SecEntry.asm | |
; | |
; Abstract: | |
; | |
; This is the code that goes from real-mode to protected mode. | |
; It consumes the reset vector, calls TempRamInit API from FSP binary. | |
; | |
;------------------------------------------------------------------------------ | |
#include "Fsp.h" | |
SECTION .text | |
extern ASM_PFX(CallPeiCoreEntryPoint) | |
extern ASM_PFX(FsptUpdDataPtr) | |
; Pcds | |
extern ASM_PFX(PcdGet32 (PcdFsptBaseAddress)) | |
;---------------------------------------------------------------------------- | |
; | |
; Procedure: _ModuleEntryPoint | |
; | |
; Input: None | |
; | |
; Output: None | |
; | |
; Destroys: Assume all registers | |
; | |
; Description: | |
; | |
; Transition to non-paged flat-model protected mode from a | |
; hard-coded GDT that provides exactly two descriptors. | |
; This is a bare bones transition to protected mode only | |
; used for a while in PEI and possibly DXE. | |
; | |
; After enabling protected mode, a far jump is executed to | |
; transfer to PEI using the newly loaded GDT. | |
; | |
; Return: None | |
; | |
; MMX Usage: | |
; MM0 = BIST State | |
; MM5 = Save time-stamp counter value high32bit | |
; MM6 = Save time-stamp counter value low32bit. | |
; | |
;---------------------------------------------------------------------------- | |
BITS 16 | |
align 4 | |
global ASM_PFX(ModuleEntryPoint) | |
ASM_PFX(ModuleEntryPoint): | |
fninit ; clear any pending Floating point exceptions | |
; | |
; Store the BIST value in mm0 | |
; | |
movd mm0, eax | |
; | |
; Save time-stamp counter value | |
; rdtsc load 64bit time-stamp counter to EDX:EAX | |
; | |
rdtsc | |
movd mm5, edx | |
movd mm6, eax | |
; | |
; Load the GDT table in GdtDesc | |
; | |
mov esi, GdtDesc | |
DB 66h | |
lgdt [cs:si] | |
; | |
; Transition to 16 bit protected mode | |
; | |
mov eax, cr0 ; Get control register 0 | |
or eax, 00000003h ; Set PE bit (bit #0) & MP bit (bit #1) | |
mov cr0, eax ; Activate protected mode | |
mov eax, cr4 ; Get control register 4 | |
or eax, 00000600h ; Set OSFXSR bit (bit #9) & OSXMMEXCPT bit (bit #10) | |
mov cr4, eax | |
; | |
; Now we're in 16 bit protected mode | |
; Set up the selectors for 32 bit protected mode entry | |
; | |
mov ax, SYS_DATA_SEL | |
mov ds, ax | |
mov es, ax | |
mov fs, ax | |
mov gs, ax | |
mov ss, ax | |
; | |
; Transition to Flat 32 bit protected mode | |
; The jump to a far pointer causes the transition to 32 bit mode | |
; | |
mov esi, ProtectedModeEntryLinearAddress | |
jmp dword far [cs:si] | |
;---------------------------------------------------------------------------- | |
; | |
; Procedure: ProtectedModeEntryPoint | |
; | |
; Input: None | |
; | |
; Output: None | |
; | |
; Destroys: Assume all registers | |
; | |
; Description: | |
; | |
; This function handles: | |
; Call two basic APIs from FSP binary | |
; Initializes stack with some early data (BIST, PEI entry, etc) | |
; | |
; Return: None | |
; | |
;---------------------------------------------------------------------------- | |
BITS 32 | |
align 4 | |
ProtectedModeEntryPoint: | |
; Find the fsp info header | |
mov edi, [ASM_PFX(PcdGet32 (PcdFsptBaseAddress))] | |
mov eax, dword [edi + FVH_SIGINATURE_OFFSET] | |
cmp eax, FVH_SIGINATURE_VALID_VALUE | |
jnz FspHeaderNotFound | |
xor eax, eax | |
mov ax, word [edi + FVH_EXTHEADER_OFFSET_OFFSET] | |
cmp ax, 0 | |
jnz FspFvExtHeaderExist | |
xor eax, eax | |
mov ax, word [edi + FVH_HEADER_LENGTH_OFFSET] ; Bypass Fv Header | |
add edi, eax | |
jmp FspCheckFfsHeader | |
FspFvExtHeaderExist: | |
add edi, eax | |
mov eax, dword [edi + FVH_EXTHEADER_SIZE_OFFSET] ; Bypass Ext Fv Header | |
add edi, eax | |
; Round up to 8 byte alignment | |
mov eax, edi | |
and al, 07h | |
jz FspCheckFfsHeader | |
and edi, 0FFFFFFF8h | |
add edi, 08h | |
FspCheckFfsHeader: | |
; Check the ffs guid | |
mov eax, dword [edi] | |
cmp eax, FSP_HEADER_GUID_DWORD1 | |
jnz FspHeaderNotFound | |
mov eax, dword [edi + 4] | |
cmp eax, FSP_HEADER_GUID_DWORD2 | |
jnz FspHeaderNotFound | |
mov eax, dword [edi + 8] | |
cmp eax, FSP_HEADER_GUID_DWORD3 | |
jnz FspHeaderNotFound | |
mov eax, dword [edi + 0Ch] | |
cmp eax, FSP_HEADER_GUID_DWORD4 | |
jnz FspHeaderNotFound | |
add edi, FFS_HEADER_SIZE_VALUE ; Bypass the ffs header | |
; Check the section type as raw section | |
mov al, byte [edi + SECTION_HEADER_TYPE_OFFSET] | |
cmp al, 019h | |
jnz FspHeaderNotFound | |
add edi, RAW_SECTION_HEADER_SIZE_VALUE ; Bypass the section header | |
jmp FspHeaderFound | |
FspHeaderNotFound: | |
jmp $ | |
FspHeaderFound: | |
; Get the fsp TempRamInit Api address | |
mov eax, dword [edi + FSP_HEADER_IMAGEBASE_OFFSET] | |
add eax, dword [edi + FSP_HEADER_TEMPRAMINIT_OFFSET] | |
; Setup the hardcode stack | |
mov esp, TempRamInitStack | |
; Call the fsp TempRamInit Api | |
jmp eax | |
TempRamInitDone: | |
cmp eax, 8000000Eh ;Check if EFI_NOT_FOUND returned. Error code for Microcode Update not found. | |
je CallSecFspInit ;If microcode not found, don't hang, but continue. | |
cmp eax, 0 ;Check if EFI_SUCCESS retuned. | |
jnz FspApiFailed | |
; ECX: start of range | |
; EDX: end of range | |
CallSecFspInit: | |
xor eax, eax | |
mov esp, edx | |
; Align the stack at DWORD | |
add esp, 3 | |
and esp, 0FFFFFFFCh | |
push edx | |
push ecx | |
push eax ; zero - no hob list yet | |
call ASM_PFX(CallPeiCoreEntryPoint) | |
FspApiFailed: | |
jmp $ | |
align 10h | |
TempRamInitStack: | |
DD TempRamInitDone | |
DD ASM_PFX(FsptUpdDataPtr); TempRamInitParams | |
; | |
; ROM-based Global-Descriptor Table for the Tiano PEI Phase | |
; | |
align 16 | |
global ASM_PFX(BootGdtTable) | |
; | |
; GDT[0]: 0x00: Null entry, never used. | |
; | |
NULL_SEL EQU $ - GDT_BASE ; Selector [0] | |
GDT_BASE: | |
ASM_PFX(BootGdtTable): | |
DD 0 | |
DD 0 | |
; | |
; Linear data segment descriptor | |
; | |
LINEAR_SEL EQU $ - GDT_BASE ; Selector [0x8] | |
DW 0FFFFh ; limit 0xFFFFF | |
DW 0 ; base 0 | |
DB 0 | |
DB 092h ; present, ring 0, data, expand-up, writable | |
DB 0CFh ; page-granular, 32-bit | |
DB 0 | |
; | |
; Linear code segment descriptor | |
; | |
LINEAR_CODE_SEL EQU $ - GDT_BASE ; Selector [0x10] | |
DW 0FFFFh ; limit 0xFFFFF | |
DW 0 ; base 0 | |
DB 0 | |
DB 09Bh ; present, ring 0, data, expand-up, not-writable | |
DB 0CFh ; page-granular, 32-bit | |
DB 0 | |
; | |
; System data segment descriptor | |
; | |
SYS_DATA_SEL EQU $ - GDT_BASE ; Selector [0x18] | |
DW 0FFFFh ; limit 0xFFFFF | |
DW 0 ; base 0 | |
DB 0 | |
DB 093h ; present, ring 0, data, expand-up, not-writable | |
DB 0CFh ; page-granular, 32-bit | |
DB 0 | |
; | |
; System code segment descriptor | |
; | |
SYS_CODE_SEL EQU $ - GDT_BASE ; Selector [0x20] | |
DW 0FFFFh ; limit 0xFFFFF | |
DW 0 ; base 0 | |
DB 0 | |
DB 09Ah ; present, ring 0, data, expand-up, writable | |
DB 0CFh ; page-granular, 32-bit | |
DB 0 | |
; | |
; Spare segment descriptor | |
; | |
SYS16_CODE_SEL EQU $ - GDT_BASE ; Selector [0x28] | |
DW 0FFFFh ; limit 0xFFFFF | |
DW 0 ; base 0 | |
DB 0Eh ; Changed from F000 to E000. | |
DB 09Bh ; present, ring 0, code, expand-up, writable | |
DB 00h ; byte-granular, 16-bit | |
DB 0 | |
; | |
; Spare segment descriptor | |
; | |
SYS16_DATA_SEL EQU $ - GDT_BASE ; Selector [0x30] | |
DW 0FFFFh ; limit 0xFFFF | |
DW 0 ; base 0 | |
DB 0 | |
DB 093h ; present, ring 0, data, expand-up, not-writable | |
DB 00h ; byte-granular, 16-bit | |
DB 0 | |
; | |
; Spare segment descriptor | |
; | |
SPARE5_SEL EQU $ - GDT_BASE ; Selector [0x38] | |
DW 0 ; limit 0 | |
DW 0 ; base 0 | |
DB 0 | |
DB 0 ; present, ring 0, data, expand-up, writable | |
DB 0 ; page-granular, 32-bit | |
DB 0 | |
GDT_SIZE EQU $ - GDT_BASE ; Size, in bytes | |
; | |
; GDT Descriptor | |
; | |
GdtDesc: ; GDT descriptor | |
DW GDT_SIZE - 1 ; GDT limit | |
DD GDT_BASE ; GDT base address | |
ProtectedModeEntryLinearAddress: | |
ProtectedModeEntryLinear: | |
DD ProtectedModeEntryPoint ; Offset of our 32 bit code | |
DW LINEAR_CODE_SEL |