#------------------------------------------------------------------------------ # # 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.S # # 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" ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdFlashFvFspBase) ASM_GLOBAL ASM_PFX(_gPcd_FixedAtBuild_PcdFlashFvFspSize) ASM_GLOBAL ASM_PFX(_TEXT_REALMODE) ASM_PFX(_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 ASM_GLOBAL ASM_PFX(_ModuleEntryPoint) ASM_PFX(_ModuleEntryPoint): fninit # clear any pending Floating point exceptions # # Store the BIST value in mm0 # movd %eax, %mm0 # # Save time-stamp counter value # rdtsc load 64bit time-stamp counter to EDX:EAX # rdtsc movd %edx, %mm5 movd %ecx, %mm6 # # Load the GDT table in GdtDesc # movl $GdtDesc, %esi .byte 0x66 lgdt %cs:(%si) # # Transition to 16 bit protected mode # movl %cr0, %eax # Get control register 0 orl $0x00000003, %eax # Set PE bit (bit #0) & MP bit (bit #1) movl %eax, %cr0 # Activate protected mode movl %cr4, %eax # Get control register 4 orl $0x00000600, %eax # Set OSFXSR bit (bit #9) & OSXMMEXCPT bit (bit #10) movl %eax, %cr4 # # Now we're in 16 bit protected mode # Set up the selectors for 32 bit protected mode entry # movw SYS_DATA_SEL, %ax movw %ax, %ds movw %ax, %es movw %ax, %fs movw %ax, %gs movw %ax, %ss # # Transition to Flat 32 bit protected mode # The jump to a far pointer causes the transition to 32 bit mode # movl ASM_PFX(ProtectedModeEntryLinearAddress), %esi jmp *%cs:(%si) ASM_GLOBAL ASM_PFX(_TEXT_PROTECTED_MODE) ASM_PFX(_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 ASM_GLOBAL ASM_PFX(ProtectedModeEntryPoint) ASM_PFX(ProtectedModeEntryPoint): # Find the fsp info header movl ASM_PFX(_gPcd_FixedAtBuild_PcdFlashFvFspBase), %edi movl ASM_PFX(_gPcd_FixedAtBuild_PcdFlashFvFspSize), %ecx movl FVH_SIGINATURE_OFFSET(%edi), %eax cmp $FVH_SIGINATURE_VALID_VALUE, %eax jnz FspHeaderNotFound xorl %eax, %eax movw FVH_EXTHEADER_OFFSET_OFFSET(%edi), %ax cmp %ax, 0 jnz FspFvExtHeaderExist xorl %eax, %eax movw FVH_HEADER_LENGTH_OFFSET(%edi), %ax # Bypass Fv Header addl %eax, %edi jmp FspCheckFfsHeader FspFvExtHeaderExist: addl %eax, %edi movl FVH_EXTHEADER_SIZE_OFFSET(%edi), %eax # Bypass Ext Fv Header addl %eax, %edi # Round up to 8 byte alignment movl %edi, %eax andb $0x07, %al jz FspCheckFfsHeader and $0xFFFFFFF8, %edi add $0x08, %edi FspCheckFfsHeader: # Check the ffs guid movl (%edi), %eax cmp $FSP_HEADER_GUID_DWORD1, %eax jnz FspHeaderNotFound movl 0x4(%edi), %eax cmp $FSP_HEADER_GUID_DWORD2, %eax jnz FspHeaderNotFound movl 0x08(%edi), %eax cmp $FSP_HEADER_GUID_DWORD3, %eax jnz FspHeaderNotFound movl 0x0c(%edi), %eax cmp $FSP_HEADER_GUID_DWORD4, %eax jnz FspHeaderNotFound add $FFS_HEADER_SIZE_VALUE, %edi # Bypass the ffs header # Check the section type as raw section movb SECTION_HEADER_TYPE_OFFSET(%edi), %al cmp $0x19, %al jnz FspHeaderNotFound addl $RAW_SECTION_HEADER_SIZE_VALUE, %edi # Bypass the section header jmp FspHeaderFound FspHeaderNotFound: jmp . FspHeaderFound: # Get the fsp TempRamInit Api address movl FSP_HEADER_IMAGEBASE_OFFSET(%edi), %eax addl FSP_HEADER_TEMPRAMINIT_OFFSET(%edi), %eax # Setup the hardcode stack movl $TempRamInitStack, %esp # Call the fsp TempRamInit Api jmp *%eax TempRamInitDone: cmp $0x0, %eax jnz FspApiFailed # ECX: start of range # EDX: end of range movl %edx, %esp pushl %edx pushl %ecx pushl %eax # zero - no hob list yet call ASM_PFX(CallPeiCoreEntryPoint) FspApiFailed: jmp . .align 0x10 TempRamInitStack: .long TempRamInitDone .long ASM_PFX(TempRamInitParams) # # ROM-based Global-Descriptor Table for the Tiano PEI Phase # .align 16 # # GDT[0]: 0x00: Null entry, never used. # .equ NULL_SEL, . - GDT_BASE # Selector [0] GDT_BASE: BootGdtTable: .long 0 .long 0 # # Linear data segment descriptor # .equ LINEAR_SEL, . - GDT_BASE # Selector [0x8] .word 0xFFFF # limit 0xFFFFF .word 0 # base 0 .byte 0 .byte 0x92 # present, ring 0, data, expand-up, writable .byte 0xCF # page-granular, 32-bit .byte 0 # # Linear code segment descriptor # .equ LINEAR_CODE_SEL, . - GDT_BASE # Selector [0x10] .word 0xFFFF # limit 0xFFFFF .word 0 # base 0 .byte 0 .byte 0x9B # present, ring 0, data, expand-up, not-writable .byte 0xCF # page-granular, 32-bit .byte 0 # # System data segment descriptor # .equ SYS_DATA_SEL, . - GDT_BASE # Selector [0x18] .word 0xFFFF # limit 0xFFFFF .word 0 # base 0 .byte 0 .byte 0x93 # present, ring 0, data, expand-up, not-writable .byte 0xCF # page-granular, 32-bit .byte 0 # # System code segment descriptor # .equ SYS_CODE_SEL, . - GDT_BASE # Selector [0x20] .word 0xFFFF # limit 0xFFFFF .word 0 # base 0 .byte 0 .byte 0x9A # present, ring 0, data, expand-up, writable .byte 0xCF # page-granular, 32-bit .byte 0 # # Spare segment descriptor # .equ SYS16_CODE_SEL, . - GDT_BASE # Selector [0x28] .word 0xFFFF # limit 0xFFFFF .word 0 # base 0 .byte 0x0E # Changed from F000 to E000. .byte 0x9B # present, ring 0, code, expand-up, writable .byte 0x00 # byte-granular, 16-bit .byte 0 # # Spare segment descriptor # .equ SYS16_DATA_SEL, . - GDT_BASE # Selector [0x30] .word 0xFFFF # limit 0xFFFF .word 0 # base 0 .byte 0 .byte 0x93 # present, ring 0, data, expand-up, not-writable .byte 0x00 # byte-granular, 16-bit .byte 0 # # Spare segment descriptor # .equ SPARE5_SEL, . - GDT_BASE # Selector [0x38] .word 0 # limit 0 .word 0 # base 0 .byte 0 .byte 0 # present, ring 0, data, expand-up, writable .byte 0 # page-granular, 32-bit .byte 0 .equ GDT_SIZE, . - BootGdtTable # Size, in bytes # # GDT Descriptor # GdtDesc: # GDT descriptor .word GDT_SIZE - 1 # GDT limit .long BootGdtTable # GDT base address ASM_PFX(ProtectedModeEntryLinearAddress): ProtectedModeEntryLinearOffset: .long ASM_PFX(ProtectedModeEntryPoint) # Offset of our 32 bit code .word LINEAR_CODE_SEL