| #------------------------------------------------------------------------------ | |
| # | |
| # Copyright (c) 2014, 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.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 $0x8000000E, %eax #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 $0x0, %eax | |
| jnz FspApiFailed | |
| # ECX: start of range | |
| # EDX: end of range | |
| CallSecFspInit: | |
| xorl %eax, %eax | |
| movl %edx, %esp | |
| # Align the stack at DWORD | |
| addl $3, %esp | |
| andl $0xFFFFFFFC, %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 |