1#------------------------------------------------------------------------------
2#
3# Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
4# This program and the accompanying materials
5# are licensed and made available under the terms and conditions of the BSD License
6# which accompanies this distribution.  The full text of the license may be found at
7# http://opensource.org/licenses/bsd-license.php.
8#
9# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11#
12# Module Name:
13#
14#  SecEntry.S
15#
16# Abstract:
17#
18#  This is the code that goes from real-mode to protected mode.
19#  It consumes the reset vector, calls TempRamInit API from FSP binary.
20#
21#------------------------------------------------------------------------------
22
23#include "Fsp.h"
24
25ASM_GLOBAL    ASM_PFX(_gPcd_FixedAtBuild_PcdFlashFvFspBase)
26ASM_GLOBAL    ASM_PFX(_gPcd_FixedAtBuild_PcdFlashFvFspSize)
27
28ASM_GLOBAL ASM_PFX(_TEXT_REALMODE)
29ASM_PFX(_TEXT_REALMODE):
30#----------------------------------------------------------------------------
31#
32# Procedure:    _ModuleEntryPoint
33#
34# Input:        None
35#
36# Output:       None
37#
38# Destroys:     Assume all registers
39#
40# Description:
41#
42#   Transition to non-paged flat-model protected mode from a
43#   hard-coded GDT that provides exactly two descriptors.
44#   This is a bare bones transition to protected mode only
45#   used for a while in PEI and possibly DXE.
46#
47#   After enabling protected mode, a far jump is executed to
48#   transfer to PEI using the newly loaded GDT.
49#
50# Return:       None
51#
52#  MMX Usage:
53#              MM0 = BIST State
54#              MM5 = Save time-stamp counter value high32bit
55#              MM6 = Save time-stamp counter value low32bit.
56#
57#----------------------------------------------------------------------------
58
59.align 4
60ASM_GLOBAL ASM_PFX(_ModuleEntryPoint)
61ASM_PFX(_ModuleEntryPoint):
62  fninit                                # clear any pending Floating point exceptions
63  #
64  # Store the BIST value in mm0
65  #
66  movd    %eax, %mm0
67
68  #
69  # Save time-stamp counter value
70  # rdtsc load 64bit time-stamp counter to EDX:EAX
71  #
72  rdtsc
73  movd    %edx, %mm5
74  movd    %ecx, %mm6
75
76  #
77  # Load the GDT table in GdtDesc
78  #
79  movl    $GdtDesc, %esi
80  .byte   0x66
81  lgdt    %cs:(%si)
82
83  #
84  # Transition to 16 bit protected mode
85  #
86  movl    %cr0, %eax                 # Get control register 0
87  orl     $0x00000003, %eax          # Set PE bit (bit #0) & MP bit (bit #1)
88  movl    %eax, %cr0                 # Activate protected mode
89
90  movl    %cr4, %eax                 # Get control register 4
91  orl     $0x00000600, %eax          # Set OSFXSR bit (bit #9) & OSXMMEXCPT bit (bit #10)
92  movl    %eax, %cr4
93
94  #
95  # Now we're in 16 bit protected mode
96  # Set up the selectors for 32 bit protected mode entry
97  #
98  movw    SYS_DATA_SEL, %ax
99  movw    %ax, %ds
100  movw    %ax, %es
101  movw    %ax, %fs
102  movw    %ax, %gs
103  movw    %ax, %ss
104
105  #
106  # Transition to Flat 32 bit protected mode
107  # The jump to a far pointer causes the transition to 32 bit mode
108  #
109  movl    ASM_PFX(ProtectedModeEntryLinearAddress), %esi
110  jmp     *%cs:(%si)
111
112ASM_GLOBAL ASM_PFX(_TEXT_PROTECTED_MODE)
113ASM_PFX(_TEXT_PROTECTED_MODE):
114
115#----------------------------------------------------------------------------
116#
117# Procedure:    ProtectedModeEntryPoint
118#
119# Input:        None
120#
121# Output:       None
122#
123# Destroys:     Assume all registers
124#
125# Description:
126#
127# This function handles:
128#   Call two basic APIs from FSP binary
129#   Initializes stack with some early data (BIST, PEI entry, etc)
130#
131# Return:       None
132#
133#----------------------------------------------------------------------------
134
135.align 4
136ASM_GLOBAL ASM_PFX(ProtectedModeEntryPoint)
137ASM_PFX(ProtectedModeEntryPoint):
138
139  # Find the fsp info header
140  movl ASM_PFX(_gPcd_FixedAtBuild_PcdFlashFvFspBase), %edi
141  movl ASM_PFX(_gPcd_FixedAtBuild_PcdFlashFvFspSize), %ecx
142
143  movl FVH_SIGINATURE_OFFSET(%edi), %eax
144  cmp  $FVH_SIGINATURE_VALID_VALUE, %eax
145  jnz  FspHeaderNotFound
146
147  xorl %eax, %eax
148  movw FVH_EXTHEADER_OFFSET_OFFSET(%edi), %ax
149  cmp  %ax, 0
150  jnz  FspFvExtHeaderExist
151
152  xorl %eax, %eax
153  movw FVH_HEADER_LENGTH_OFFSET(%edi), %ax   # Bypass Fv Header
154  addl %eax, %edi
155  jmp  FspCheckFfsHeader
156
157FspFvExtHeaderExist:
158  addl %eax, %edi
159  movl FVH_EXTHEADER_SIZE_OFFSET(%edi), %eax  # Bypass Ext Fv Header
160  addl %eax, %edi
161
162  # Round up to 8 byte alignment
163  movl %edi, %eax
164  andb $0x07, %al
165  jz FspCheckFfsHeader
166
167  and  $0xFFFFFFF8, %edi
168  add  $0x08, %edi
169
170FspCheckFfsHeader:
171  # Check the ffs guid
172  movl (%edi), %eax
173  cmp  $FSP_HEADER_GUID_DWORD1, %eax
174  jnz  FspHeaderNotFound
175
176  movl 0x4(%edi), %eax
177  cmp  $FSP_HEADER_GUID_DWORD2, %eax
178  jnz  FspHeaderNotFound
179
180  movl 0x08(%edi), %eax
181  cmp  $FSP_HEADER_GUID_DWORD3, %eax
182  jnz  FspHeaderNotFound
183
184  movl 0x0c(%edi), %eax
185  cmp  $FSP_HEADER_GUID_DWORD4, %eax
186  jnz  FspHeaderNotFound
187
188  add  $FFS_HEADER_SIZE_VALUE, %edi        # Bypass the ffs header
189
190  # Check the section type as raw section
191  movb SECTION_HEADER_TYPE_OFFSET(%edi), %al
192  cmp  $0x19, %al
193  jnz  FspHeaderNotFound
194
195  addl $RAW_SECTION_HEADER_SIZE_VALUE, %edi  # Bypass the section header
196  jmp  FspHeaderFound
197
198FspHeaderNotFound:
199  jmp  .
200
201FspHeaderFound:
202  # Get the fsp TempRamInit Api address
203  movl FSP_HEADER_IMAGEBASE_OFFSET(%edi), %eax
204  addl FSP_HEADER_TEMPRAMINIT_OFFSET(%edi), %eax
205
206  # Setup the hardcode stack
207  movl $TempRamInitStack, %esp
208
209  # Call the fsp TempRamInit Api
210  jmp  *%eax
211
212TempRamInitDone:
213  cmp  $0x8000000E, %eax   #Check if EFI_NOT_FOUND returned. Error code for Microcode Update not found.
214  je   CallSecFspInit      #If microcode not found, don't hang, but continue.
215
216  cmp  $0x0, %eax
217  jnz  FspApiFailed
218
219  #   ECX: start of range
220  #   EDX: end of range
221CallSecFspInit:
222  xorl    %eax, %eax
223  movl    %edx, %esp
224
225  # Align the stack at DWORD
226  addl  $3, %esp
227  andl  $0xFFFFFFFC, %esp
228
229  pushl   %edx
230  pushl   %ecx
231  pushl   %eax # zero - no hob list yet
232  call ASM_PFX(CallPeiCoreEntryPoint)
233
234FspApiFailed:
235  jmp .
236
237.align 0x10
238TempRamInitStack:
239    .long  TempRamInitDone
240    .long  ASM_PFX(TempRamInitParams)
241
242#
243# ROM-based Global-Descriptor Table for the Tiano PEI Phase
244#
245.align 16
246
247#
248# GDT[0]: 0x00: Null entry, never used.
249#
250.equ NULL_SEL,             . - GDT_BASE    # Selector [0]
251GDT_BASE:
252BootGdtTable:       .long  0
253                    .long  0
254#
255# Linear data segment descriptor
256#
257.equ LINEAR_SEL,           . - GDT_BASE    # Selector [0x8]
258    .word  0xFFFF                          # limit 0xFFFFF
259    .word  0                               # base 0
260    .byte  0
261    .byte  0x92                            # present, ring 0, data, expand-up, writable
262    .byte  0xCF                            # page-granular, 32-bit
263    .byte  0
264#
265# Linear code segment descriptor
266#
267.equ LINEAR_CODE_SEL,      . - GDT_BASE    # Selector [0x10]
268    .word  0xFFFF                          # limit 0xFFFFF
269    .word  0                               # base 0
270    .byte  0
271    .byte  0x9B                            # present, ring 0, data, expand-up, not-writable
272    .byte  0xCF                            # page-granular, 32-bit
273    .byte  0
274#
275# System data segment descriptor
276#
277.equ SYS_DATA_SEL,         . - GDT_BASE    # Selector [0x18]
278    .word  0xFFFF                          # limit 0xFFFFF
279    .word  0                               # base 0
280    .byte  0
281    .byte  0x93                            # present, ring 0, data, expand-up, not-writable
282    .byte  0xCF                            # page-granular, 32-bit
283    .byte  0
284
285#
286# System code segment descriptor
287#
288.equ SYS_CODE_SEL,         . - GDT_BASE    # Selector [0x20]
289    .word  0xFFFF                          # limit 0xFFFFF
290    .word  0                               # base 0
291    .byte  0
292    .byte  0x9A                            # present, ring 0, data, expand-up, writable
293    .byte  0xCF                            # page-granular, 32-bit
294    .byte  0
295#
296# Spare segment descriptor
297#
298.equ SYS16_CODE_SEL,       . - GDT_BASE    # Selector [0x28]
299    .word  0xFFFF                          # limit 0xFFFFF
300    .word  0                               # base 0
301    .byte  0x0E                            # Changed from F000 to E000.
302    .byte  0x9B                            # present, ring 0, code, expand-up, writable
303    .byte  0x00                            # byte-granular, 16-bit
304    .byte  0
305#
306# Spare segment descriptor
307#
308.equ SYS16_DATA_SEL,       . - GDT_BASE    # Selector [0x30]
309    .word  0xFFFF                          # limit 0xFFFF
310    .word  0                               # base 0
311    .byte  0
312    .byte  0x93                            # present, ring 0, data, expand-up, not-writable
313    .byte  0x00                            # byte-granular, 16-bit
314    .byte  0
315
316#
317# Spare segment descriptor
318#
319.equ SPARE5_SEL,           . - GDT_BASE    # Selector [0x38]
320    .word  0                               # limit 0
321    .word  0                               # base 0
322    .byte  0
323    .byte  0                               # present, ring 0, data, expand-up, writable
324    .byte  0                               # page-granular, 32-bit
325    .byte  0
326.equ GDT_SIZE,             . - BootGdtTable    # Size, in bytes
327
328#
329# GDT Descriptor
330#
331GdtDesc:                                # GDT descriptor
332    .word  GDT_SIZE - 1                    # GDT limit
333    .long  BootGdtTable                    # GDT base address
334
335ASM_PFX(ProtectedModeEntryLinearAddress):
336ProtectedModeEntryLinearOffset:
337  .long      ASM_PFX(ProtectedModeEntryPoint)  # Offset of our 32 bit code
338  .word      LINEAR_CODE_SEL
339