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