;------------------------------------------------------------------------------ ; ; Copyright (c) 2014, Intel Corporation. All rights reserved.
; 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" .686p .xmm .model small, c EXTRN CallPeiCoreEntryPoint:NEAR EXTRN TempRamInitParams:FAR ; Pcds EXTRN PcdGet32 (PcdFlashFvFspBase):DWORD EXTRN PcdGet32 (PcdFlashFvFspSize):DWORD _TEXT_REALMODE SEGMENT PARA PUBLIC USE16 'CODE' ASSUME CS:_TEXT_REALMODE, DS:_TEXT_REALMODE ;---------------------------------------------------------------------------- ; ; 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. ; ;---------------------------------------------------------------------------- align 4 _ModuleEntryPoint PROC NEAR C PUBLIC 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, OFFSET GdtDesc DB 66h lgdt fword ptr 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, offset ProtectedModeEntryLinearAddress jmp fword ptr cs:[si] _ModuleEntryPoint ENDP _TEXT_REALMODE ENDS _TEXT_PROTECTED_MODE SEGMENT PARA PUBLIC USE32 'CODE' ASSUME CS:_TEXT_PROTECTED_MODE, DS:_TEXT_PROTECTED_MODE ;---------------------------------------------------------------------------- ; ; 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 ; ;---------------------------------------------------------------------------- align 4 ProtectedModeEntryPoint PROC NEAR PUBLIC ; Find the fsp info header mov edi, PcdGet32 (PcdFlashFvFspBase) mov ecx, PcdGet32 (PcdFlashFvFspSize) mov eax, dword ptr [edi + FVH_SIGINATURE_OFFSET] cmp eax, FVH_SIGINATURE_VALID_VALUE jnz FspHeaderNotFound xor eax, eax mov ax, word ptr [edi + FVH_EXTHEADER_OFFSET_OFFSET] cmp ax, 0 jnz FspFvExtHeaderExist xor eax, eax mov ax, word ptr [edi + FVH_HEADER_LENGTH_OFFSET] ; Bypass Fv Header add edi, eax jmp FspCheckFfsHeader FspFvExtHeaderExist: add edi, eax mov eax, dword ptr [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 ptr [edi] cmp eax, FSP_HEADER_GUID_DWORD1 jnz FspHeaderNotFound mov eax, dword ptr [edi + 4] cmp eax, FSP_HEADER_GUID_DWORD2 jnz FspHeaderNotFound mov eax, dword ptr [edi + 8] cmp eax, FSP_HEADER_GUID_DWORD3 jnz FspHeaderNotFound mov eax, dword ptr [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 ptr [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 ptr [edi + FSP_HEADER_IMAGEBASE_OFFSET] add eax, dword ptr [edi + FSP_HEADER_TEMPRAMINIT_OFFSET] ; Setup the hardcode stack mov esp, OFFSET TempRamInitStack ; Call the fsp TempRamInit Api jmp eax TempRamInitDone: cmp eax, 0 jnz FspApiFailed ; ECX: start of range ; EDX: end of range mov esp, edx push edx push ecx push eax ; zero - no hob list yet call CallPeiCoreEntryPoint FspApiFailed: jmp $ align 10h TempRamInitStack: DD OFFSET TempRamInitDone DD OFFSET TempRamInitParams ProtectedModeEntryPoint ENDP ; ; ROM-based Global-Descriptor Table for the Tiano PEI Phase ; align 16 PUBLIC BootGdtTable ; ; GDT[0]: 0x00: Null entry, never used. ; NULL_SEL EQU $ - GDT_BASE ; Selector [0] GDT_BASE: 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 $ - BootGdtTable ; Size, in bytes ; ; GDT Descriptor ; GdtDesc: ; GDT descriptor DW GDT_SIZE - 1 ; GDT limit DD OFFSET BootGdtTable ; GDT base address ProtectedModeEntryLinearAddress LABEL FWORD ProtectedModeEntryLinearOffset LABEL DWORD DD OFFSET ProtectedModeEntryPoint ; Offset of our 32 bit code DW LINEAR_CODE_SEL _TEXT_PROTECTED_MODE ENDS END