blob: 8bae7c55db20f6f1ec2abf884761ae5da5839d09 [file] [log] [blame]
;------------------------------------------------------------------------------
;
; 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