Contributed-under: TianoCore Contribution Agreement 1.0 Signed off by: Jiewen Yao <jiewen.yao@intel.com> Reviewed by: Ravi Rangarajan <ravi.p.rangarajan@intel.com> Reviewed by: Maurice Ma <maurice.ma@intel.com> Reviewed by: Giri Mudusuru <giri.p.mudusuru@intel.com> Reviewed by: Liming Gao <liming.gao@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15676 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			326 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			326 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| #------------------------------------------------------------------------------
 | |
| #
 | |
| # 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(_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    $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 PcdGet32 (PcdFlashFvFspBase), %edi
 | |
|   movl PcdGet32 (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  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      ProtectedModeEntryPoint  # Offset of our 32 bit code
 | |
|   .word      LINEAR_CODE_SEL
 |