]> git.proxmox.com Git - mirror_edk2.git/blob - QuarkPlatformPkg/Library/PlatformSecLib/Ia32/Flat32.S
QuarkPlatformPkg/PlatformSecLib: Sync Flat32.S with Flat32.asm
[mirror_edk2.git] / QuarkPlatformPkg / Library / PlatformSecLib / Ia32 / Flat32.S
1 #------------------------------------------------------------------------------
2 #
3 # Copyright (c) 2013 - 2015 Intel Corporation.
4 #
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
9 #
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 #
13 # Module Name:
14 #
15 # Flat32.S
16 #
17 # Abstract:
18 #
19 # This is the code that goes from real-mode to protected mode.
20 # It consumes the reset vector, configures the stack.
21 #
22 #
23 #------------------------------------------------------------------------------
24
25 .macro RET32
26 jmp *%esp
27 .endm
28
29 #
30 # ROM/SPI/MEMORY Definitions
31 #
32 .equ QUARK_DDR3_MEM_BASE_ADDRESS, (0x000000000) # Memory Base Address = 0
33 .equ QUARK_MAX_DDR3_MEM_SIZE_BYTES, (0x80000000) # DDR3 Memory Size = 2GB
34 .equ QUARK_ESRAM_MEM_SIZE_BYTES, (0x00080000) # eSRAM Memory Size = 512K
35 .equ QUARK_STACK_SIZE_BYTES, (0x008000) # Quark stack size = 32K
36
37 #
38 # RTC/CMOS definitions
39 #
40 .equ RTC_INDEX, (0x70)
41 .equ NMI_DISABLE, (0x80) # Bit7=1 disables NMI
42 .equ NMI_ENABLE, (0x00) # Bit7=0 disables NMI
43 .equ RTC_DATA, (0x71)
44
45 #
46 # PCI Configuration definitions
47 #
48 .equ PCI_CFG, (0x80000000) # PCI configuration access mechanism
49 .equ PCI_ADDRESS_PORT, (0xCF8)
50 .equ PCI_DATA_PORT, (0xCFC)
51
52 #
53 # Quark PCI devices
54 #
55 .equ HOST_BRIDGE_PFA, (0x0000) # B0:D0:F0 (Host Bridge)
56 .equ ILB_PFA, (0x00F8) # B0:D31:F0 (Legacy Block)
57
58 #
59 # ILB PCI Config Registers
60 #
61 .equ BDE, (0x0D4) # BIOS Decode Enable register
62 .equ DECODE_ALL_REGIONS_ENABLE, (0xFF000000) # Decode all BIOS decode ranges
63
64 #
65 # iLB Reset Register
66 #
67 .equ ILB_RESET_REG, (0x0CF9)
68 .equ CF9_WARM_RESET, (0x02)
69 .equ CF9_COLD_RESET, (0x08)
70
71 #
72 # Host Bridge PCI Config Registers
73 #
74 .equ MESSAGE_BUS_CONTROL_REG, (0xD0) # Message Bus Control Register
75 .equ SB_OPCODE_FIELD, (0x18) # Bit location of Opcode field
76 .equ OPCODE_SIDEBAND_REG_READ, (0x10) # Read opcode
77 .equ OPCODE_SIDEBAND_REG_WRITE, (0x11) # Write opcode
78 .equ OPCODE_SIDEBAND_ALT_REG_READ, (0x06) # Alternate Read opcode
79 .equ OPCODE_SIDEBAND_ALT_REG_WRITE, (0x07) # Alternate Write opcode
80 .equ OPCODE_WARM_RESET_REQUEST, (0xF4) # Reset Warm
81 .equ OPCODE_COLD_RESET_REQUEST, (0xF5) # Reset Cold
82 .equ SB_PORT_FIELD, (0x10) # Bit location of Port ID field
83 .equ MEMORY_ARBITER_PORT_ID, (0x00)
84 .equ HOST_BRIDGE_PORT_ID, (0x03)
85 .equ RMU_PORT_ID, (0x04)
86 .equ MEMORY_MANAGER_PORT_ID, (0x05)
87 .equ SOC_UNIT_PORT_ID, (0x31)
88 .equ SB_ADDR_FIELD, (0x08) # Bit location of Register field
89 .equ SB_BE_FIELD, (0x04) # Bit location of Byte Enables field
90 .equ ALL_BYTE_EN, (0x0F) # All Byte Enables
91 .equ MESSAGE_DATA_REG, (0xD4) # Message Data Register
92
93 #
94 # Memory Arbiter Config Registers
95 #
96 .equ AEC_CTRL_OFFSET, (0x00)
97
98 #
99 # Host Bridge Config Registers
100 #
101 .equ HMISC2_OFFSET, (0x03) # PCI configuration access mechanism
102 .equ OR_PM_FIELD, (0x10)
103 .equ SMI_EN, (0x00080000)
104
105 .equ HMBOUND_OFFSET, (0x08)
106 .equ HMBOUND_ADDRESS, (QUARK_DDR3_MEM_BASE_ADDRESS + QUARK_MAX_DDR3_MEM_SIZE_BYTES + QUARK_ESRAM_MEM_SIZE_BYTES)
107 .equ HMBOUND_LOCK, (0x01)
108 .equ HECREG_OFFSET, (0x09)
109 .equ EC_BASE, (0xE0000000)
110 .equ EC_ENABLE, (0x01)
111 .equ HLEGACY_OFFSET, (0x0A)
112 .equ NMI, (0x00004000)
113 .equ SMI, (0x00001000)
114 .equ INTR, (0x00000400)
115
116 #
117 # Memory Manager Config Registers
118 #
119 .equ ESRAMPGCTRL_BLOCK_OFFSET, (0x82)
120 .equ BLOCK_ENABLE_PG, (0x10000000)
121 .equ BIMRVCTL_OFFSET, (0x19)
122 .equ ENABLE_IMR_INTERRUPT, (0x80000000)
123
124 #
125 # SOC UNIT Debug Registers
126 #
127 .equ CFGSTICKY_W1_OFFSET, (0x50)
128 .equ FORCE_COLD_RESET, (0x00000001)
129 .equ CFGSTICKY_RW_OFFSET, (0x51)
130 .equ RESET_FOR_ESRAM_LOCK, (0x00000020)
131 .equ RESET_FOR_HMBOUND_LOCK, (0x00000040)
132 .equ CFGNONSTICKY_W1_OFFSET, (0x52)
133 .equ FORCE_WARM_RESET, (0x00000001)
134
135 #
136 # CR0 cache control bit definition
137 #
138 .equ CR0_CACHE_DISABLE, 0x040000000
139 .equ CR0_NO_WRITE, 0x020000000
140
141 ASM_GLOBAL ASM_PFX(PcdGet32(PcdEsramStage1Base))
142
143
144 #
145 # Contrary to the name, this file contains 16 bit code as well.
146 #
147 .text
148 #----------------------------------------------------------------------------
149 #
150 # Procedure: _ModuleEntryPoint
151 #
152 # Input: None
153 #
154 # Output: None
155 #
156 # Destroys: Assume all registers
157 #
158 # Description:
159 #
160 # Transition to non-paged flat-model protected mode from a
161 # hard-coded GDT that provides exactly two descriptors.
162 # This is a bare bones transition to protected mode only
163 # used for a while in PEI and possibly DXE.
164 #
165 # After enabling protected mode, a far jump is executed to
166 # transfer to PEI using the newly loaded GDT.
167 #
168 # Return: None
169 #
170 #----------------------------------------------------------------------------
171 ASM_GLOBAL ASM_PFX(_ModuleEntryPoint)
172 ASM_PFX(_ModuleEntryPoint):
173
174 #
175 # Warm Reset (INIT#) check.
176 #
177 .byte 0xbe,0x00,0xf0 #movw $0xF000, %si
178 .byte 0x8e,0xde #movw %si, %ds
179 .byte 0xbe,0xf0,0xff #movw $0xFFF0, %si
180 .byte 0x80,0x3c,0xea #cmpb $0xEA, (%si) # Is it warm reset ?
181 jne NotWarmReset # Jump if not.
182 .byte 0xb0,0x08 #movb $0x08, %al
183 .byte 0xba,0xf9,0x0c #movw $0xcf9, %dx
184 .byte 0xee #outb %al, %dx
185 .byte 0xb0,0x55 #movb $0x55, %al
186 .byte 0xe6,0x80 #outb %al, $0x80
187 jmp .
188 NotWarmReset:
189 .byte 0x66,0x8b,0xe8 #movl %eax, %ebp
190
191 #
192 # Load the GDT table in GdtDesc
193 #
194 .byte 0x66,0xbe #movl $GdtDesc, %esi
195 .long GdtDesc
196
197 .byte 0x66,0x2e,0x0f,0x01,0x14 #lgdt %cs:(%si)
198
199 #
200 # Transition to 16 bit protected mode
201 #
202 .byte 0x0f,0x20,0xc0 #movl %cr0, %eax # Get control register 0
203 .byte 0x66,0x83,0xc8,0x03 #orl $0x0000003, %eax # Set PE bit (bit #0) & MP bit (bit #1)
204 .byte 0x0f,0x22,0xc0 #movl %eax, %cr0 # Activate protected mode
205
206 #
207 # Now we're in 16 bit protected mode
208 # Set up the selectors for 32 bit protected mode entry
209 #
210 .byte 0xb8 #movw SYS_DATA_SEL, %ax
211 .word SYS_DATA_SEL
212
213 .byte 0x8e,0xd8 #movw %ax, %ds
214 .byte 0x8e,0xc0 #movw %ax, %es
215 .byte 0x8e,0xe0 #movw %ax, %fs
216 .byte 0x8e,0xe8 #movw %ax, %gs
217 .byte 0x8e,0xd0 #movw %ax, %ss
218
219 #
220 # Transition to Flat 32 bit protected mode
221 # The jump to a far pointer causes the transition to 32 bit mode
222 #
223 .byte 0x66,0xbe #movl ProtectedModeEntryLinearAddress, %esi
224 .long ProtectedModeEntryLinearAddress
225 .byte 0x66,0x2e,0xff,0x2c #jmp %cs:(%esi)
226
227 #
228 # Protected mode portion initializes stack, configures cache, and calls C entry point
229 #
230
231 #----------------------------------------------------------------------------
232 #
233 # Procedure: ProtectedModeEntryPoint
234 #
235 # Input: Executing in 32 Bit Protected (flat) mode
236 # cs: 0-4GB
237 # ds: 0-4GB
238 # es: 0-4GB
239 # fs: 0-4GB
240 # gs: 0-4GB
241 # ss: 0-4GB
242 #
243 # Output: This function never returns
244 #
245 # Destroys:
246 # ecx
247 # edi
248 # esi
249 # esp
250 #
251 # Description:
252 # Perform any essential early platform initilaisation
253 # Setup a stack
254 # Transfer control to EDKII code in eSRAM
255 #
256 #----------------------------------------------------------------------------
257 ProtectedModeEntryPoint:
258 leal L0, %esp
259 jmp stackless_EarlyPlatformInit
260 L0:
261
262 #
263 # Set up stack pointer
264 #
265 movl ASM_PFX(PcdGet32(PcdEsramStage1Base)), %esp
266 movl $QUARK_STACK_SIZE_BYTES, %esi
267 addl %esi, %esp # ESP = top of stack (stack grows downwards).
268
269 #
270 # Store the the BIST value in EBP
271 #
272 movl $0, %ebp # No processor BIST on Quark
273
274 #
275 # Push processor count to stack first, then BIST status (AP then BSP)
276 #
277 movl $1, %eax
278 cpuid
279 shrl $16, %ebx
280 andl $0x000000FF, %ebx
281 cmpb $1, %bl
282 jae PushProcessorCount
283
284 #
285 # Some processors report 0 logical processors. Effectively 0 = 1.
286 # So we fix up the processor count
287 #
288 incl %ebx
289
290 PushProcessorCount:
291 pushl %ebx
292
293 #
294 # We need to implement a long-term solution for BIST capture. For now, we just copy BSP BIST
295 # for all processor threads
296 #
297 xorl %ecx, %ecx
298 movb %bl, %cl
299
300 PushBist:
301 pushl %ebp
302 loop PushBist
303
304 #
305 # Pass Control into the PEI Core
306 #
307 call PlatformSecLibStartup
308
309 #
310 # PEI Core should never return to here, this is just to capture an invalid return.
311 #
312 jmp .
313
314 #----------------------------------------------------------------------------
315 #
316 # Procedure: stackless_EarlyPlatformInit
317 #
318 # Input: esp - Return address
319 #
320 # Output: None
321 #
322 # Destroys: Assume all registers
323 #
324 # Description:
325 # Any early platform initialisation required
326 #
327 # Return:
328 # None
329 #
330 #----------------------------------------------------------------------------
331 stackless_EarlyPlatformInit:
332
333 #
334 # Save return address
335 #
336 movl %esp, %ebp
337
338 #
339 # Ensure cache is disabled.
340 #
341 movl %cr0, %eax
342 orl $(CR0_CACHE_DISABLE + CR0_NO_WRITE), %eax
343 invd
344 movl %eax, %cr0
345
346 #
347 # Disable NMI operation
348 # Good convention suggests you should read back RTC data port after
349 # accessing the RTC index port.
350 #
351 movb $(NMI_DISABLE), %al
352 movw $(RTC_INDEX), %dx
353 outb %al, %dx
354 movw $(RTC_DATA), %dx
355 inb %dx, %al
356
357 #
358 # Disable SMI (Disables SMI wire, not SMI messages)
359 #
360 movl $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMISC2_OFFSET << SB_ADDR_FIELD)), %ecx
361 leal L1, %esp
362 jmp stackless_SideBand_Read
363 L1:
364 andl $(~SMI_EN), %eax
365 movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMISC2_OFFSET << SB_ADDR_FIELD)), %ecx
366 leal L2, %esp
367 jmp stackless_SideBand_Write
368 L2:
369
370 #
371 # Before we get going, check SOC Unit Registers to see if we are required to issue a warm/cold reset
372 #
373 movl $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGNONSTICKY_W1_OFFSET << SB_ADDR_FIELD)), %ecx
374 leal L3, %esp
375 jmp stackless_SideBand_Read
376 L3:
377 andl $(FORCE_WARM_RESET), %eax
378 jz TestForceColdReset # Zero means bit clear, we're not requested to warm reset so continue as normal
379 jmp IssueWarmReset
380
381 TestForceColdReset:
382 movl $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGNONSTICKY_W1_OFFSET << SB_ADDR_FIELD)), %ecx
383 leal L4, %esp
384 jmp stackless_SideBand_Read
385 L4:
386 andl $(FORCE_COLD_RESET), %eax
387 jz TestHmboundLock # Zero means bit clear, we're not requested to cold reset so continue as normal
388 jmp IssueColdReset
389
390 #
391 # Before setting HMBOUND, check it's not locked
392 #
393 TestHmboundLock:
394 movl $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMBOUND_OFFSET << SB_ADDR_FIELD)), %ecx
395 leal L5, %esp
396 jmp stackless_SideBand_Read
397 L5:
398 andl $(HMBOUND_LOCK), %eax
399 jz ConfigHmbound # Zero means bit clear, we have the config we want so continue as normal
400 #
401 # Failed to config - store sticky bit debug
402 #
403 movl $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx
404 leal L6, %esp
405 jmp stackless_SideBand_Read
406 L6:
407 orl $(RESET_FOR_HMBOUND_LOCK), %eax
408 movl $((OPCODE_SIDEBAND_ALT_REG_WRITE << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx
409 leal L7, %esp
410 jmp stackless_SideBand_Write
411 L7:
412 jmp IssueWarmReset
413
414 #
415 # Set up the HMBOUND register
416 #
417 ConfigHmbound:
418 movl $(HMBOUND_ADDRESS), %eax # Data (Set HMBOUND location)
419 movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMBOUND_OFFSET << SB_ADDR_FIELD)), %ecx
420 leal L8, %esp
421 jmp stackless_SideBand_Write
422 L8:
423
424 #
425 # Enable interrupts to Remote Management Unit when a IMR/SMM/HMBOUND violation occurs.
426 #
427 movl $(ENABLE_IMR_INTERRUPT), %eax # Data (Set interrupt enable mask)
428 movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (MEMORY_MANAGER_PORT_ID << SB_PORT_FIELD) | (BIMRVCTL_OFFSET << SB_ADDR_FIELD)), %ecx
429 leal L9, %esp
430 jmp stackless_SideBand_Write
431 L9:
432
433 #
434 # Set eSRAM address
435 #
436 movl ASM_PFX(PcdGet32(PcdEsramStage1Base)), %eax # Data (Set eSRAM location)
437 shr $(0x18), %eax
438 addl $(BLOCK_ENABLE_PG), %eax
439 movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (MEMORY_MANAGER_PORT_ID << SB_PORT_FIELD) | (ESRAMPGCTRL_BLOCK_OFFSET << SB_ADDR_FIELD)), %ecx
440 leal L10, %esp
441 jmp stackless_SideBand_Write
442 L10:
443
444 #
445 # Check that we're not blocked from setting the config that we want.
446 #
447 movl $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (MEMORY_MANAGER_PORT_ID << SB_PORT_FIELD) | (ESRAMPGCTRL_BLOCK_OFFSET << SB_ADDR_FIELD)), %ecx
448 leal L11, %esp
449 jmp stackless_SideBand_Read
450 L11:
451 andl $(BLOCK_ENABLE_PG), %eax
452 jnz ConfigPci # Non-zero means bit set, we have the config we want so continue as normal
453 #
454 # Failed to config - store sticky bit debug
455 #
456 movl $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx
457 leal L12, %esp
458 jmp stackless_SideBand_Read
459 L12:
460 orl $(RESET_FOR_ESRAM_LOCK), %eax # Set the bit we're interested in
461 movl $((OPCODE_SIDEBAND_ALT_REG_WRITE << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx
462 leal L13, %esp
463 jmp stackless_SideBand_Write
464 L13:
465 jmp IssueWarmReset
466
467 #
468 # Enable PCIEXBAR
469 #
470 ConfigPci:
471 movl $(EC_BASE + EC_ENABLE), %eax # Data
472 movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (MEMORY_ARBITER_PORT_ID << SB_PORT_FIELD) | (AEC_CTRL_OFFSET << SB_ADDR_FIELD)), %ecx
473 leal L14, %esp
474 jmp stackless_SideBand_Write
475 L14:
476
477 movl $(EC_BASE + EC_ENABLE), %eax # Data
478 movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HECREG_OFFSET << SB_ADDR_FIELD)), %ecx
479 leal L15, %esp
480 jmp stackless_SideBand_Write
481 L15:
482
483 #
484 # Open up full 8MB SPI decode
485 #
486 movl $(PCI_CFG | (ILB_PFA << 8) | BDE), %ebx # PCI Configuration address
487 movl $(DECODE_ALL_REGIONS_ENABLE), %eax
488 leal L16, %esp
489 jmp stackless_PCIConfig_Write
490 L16:
491
492 #
493 # Enable NMI operation
494 # Good convention suggests you should read back RTC data port after
495 # accessing the RTC index port.
496 #
497 movb $(NMI_ENABLE), %al
498 movw $(RTC_INDEX), %dx
499 outb %al, %dx
500 movw $(RTC_DATA), %dx
501 inb %dx, %al
502
503 #
504 # Clear Host Bridge SMI, NMI, INTR fields
505 #
506 movl $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HLEGACY_OFFSET << SB_ADDR_FIELD)), %ecx
507 leal L21, %esp
508 jmp stackless_SideBand_Read
509 L21:
510 andl $~(NMI + SMI + INTR), %eax # Clear NMI, SMI, INTR fields
511 movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HLEGACY_OFFSET << SB_ADDR_FIELD)), %ecx
512 leal L22, %esp
513 jmp stackless_SideBand_Write
514 L22:
515
516 #
517 # Restore return address
518 #
519 movl %ebp, %esp
520 RET32
521
522 IssueWarmReset:
523 #
524 # Issue Warm Reset request to Remote Management Unit via iLB
525 #
526 movw $(CF9_WARM_RESET), %ax
527 movw $(ILB_RESET_REG), %dx
528 outw %ax, %dx
529 jmp . # Stay here until we are reset.
530
531 IssueColdReset:
532 #
533 # Issue Cold Reset request to Remote Management Unit via iLB
534 #
535 movw $(CF9_COLD_RESET), %ax
536 movw $(ILB_RESET_REG), %dx
537 outw %ax, %dx
538 jmp . # Stay here until we are reset.
539
540 #----------------------------------------------------------------------------
541 #
542 # Procedure: stackless_SideBand_Read
543 #
544 # Input: esp - return address
545 # ecx[15:8] - Register offset
546 # ecx[23:16] - Port ID
547 # ecx[31:24] - Opcode
548 #
549 # Output: eax - Data read
550 #
551 # Destroys:
552 # eax
553 # ebx
554 # cl
555 # esi
556 #
557 # Description:
558 # Perform requested sideband read
559 #
560 #----------------------------------------------------------------------------
561 stackless_SideBand_Read:
562
563 movl %esp, %esi # Save the return address
564
565 #
566 # Load the SideBand Packet Register to generate the transaction
567 #
568 movl $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_BUS_CONTROL_REG)), %ebx # PCI Configuration address
569 movb $(ALL_BYTE_EN << SB_BE_FIELD), %cl # Set all Byte Enable bits
570 xchgl %ecx, %eax
571 leal L17, %esp
572 jmp stackless_PCIConfig_Write
573 L17:
574 xchgl %ecx, %eax
575
576 #
577 # Read the SideBand Data Register
578 #
579 movl $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_DATA_REG)), %ebx # PCI Configuration address
580 leal L18, %esp
581 jmp stackless_PCIConfig_Read
582 L18:
583
584 movl %esi, %esp # Restore the return address
585 RET32
586
587
588 #----------------------------------------------------------------------------
589 #
590 # Procedure: stackless_SideBand_Write
591 #
592 # Input: esp - return address
593 # eax - Data
594 # ecx[15:8] - Register offset
595 # ecx[23:16] - Port ID
596 # ecx[31:24] - Opcode
597 #
598 # Output: None
599 #
600 # Destroys:
601 # ebx
602 # cl
603 # esi
604 #
605 # Description:
606 # Perform requested sideband write
607 #
608 #
609 #----------------------------------------------------------------------------
610 stackless_SideBand_Write:
611
612 movl %esp, %esi # Save the return address
613
614 #
615 # Load the SideBand Data Register with the data
616 #
617 movl $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_DATA_REG)), %ebx # PCI Configuration address
618 leal L19, %esp
619 jmp stackless_PCIConfig_Write
620 L19:
621
622 #
623 # Load the SideBand Packet Register to generate the transaction
624 #
625 movl $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_BUS_CONTROL_REG)), %ebx # PCI Configuration address
626 movb $(ALL_BYTE_EN << SB_BE_FIELD), %cl # Set all Byte Enable bits
627 xchgl %ecx, %eax
628 leal L20, %esp
629 jmp stackless_PCIConfig_Write
630 L20:
631 xchgl %ecx, %eax
632
633 movl %esi, %esp # Restore the return address
634 RET32
635
636
637 #----------------------------------------------------------------------------
638 #
639 # Procedure: stackless_PCIConfig_Write
640 #
641 # Input: esp - return address
642 # eax - Data to write
643 # ebx - PCI Config Address
644 #
645 # Output: None
646 #
647 # Destroys:
648 # dx
649 #
650 # Description:
651 # Perform a DWORD PCI Configuration write
652 #
653 #----------------------------------------------------------------------------
654 stackless_PCIConfig_Write:
655
656 #
657 # Write the PCI Config Address to the address port
658 #
659 xchgl %ebx, %eax
660 movw $(PCI_ADDRESS_PORT), %dx
661 outl %eax, %dx
662 xchgl %ebx, %eax
663
664 #
665 # Write the PCI DWORD Data to the data port
666 #
667 movw $(PCI_DATA_PORT), %dx
668 outl %eax, %dx
669
670 RET32
671
672
673 #----------------------------------------------------------------------------
674 #
675 # Procedure: stackless_PCIConfig_Read
676 #
677 # Input: esp - return address
678 # ebx - PCI Config Address
679 #
680 # Output: eax - Data read
681 #
682 # Destroys:
683 # eax
684 # dx
685 #
686 # Description:
687 # Perform a DWORD PCI Configuration read
688 #
689 #----------------------------------------------------------------------------
690 stackless_PCIConfig_Read:
691
692 #
693 # Write the PCI Config Address to the address port
694 #
695 xchgl %ebx, %eax
696 movw $(PCI_ADDRESS_PORT), %dx
697 outl %eax, %dx
698 xchgl %ebx, %eax
699
700 #
701 # Read the PCI DWORD Data from the data port
702 #
703 movw $(PCI_DATA_PORT), %dx
704 inl %dx, %eax
705
706 RET32
707
708
709 #
710 # ROM-based Global-Descriptor Table for the Tiano PEI Phase
711 #
712 .align 16
713 #
714 # GDT[0]: 000h: Null entry, never used.
715 #
716
717 GDT_BASE:
718 BootGdtTable:
719 # null descriptor
720 .equ NULL_SEL, . - GDT_BASE # Selector [0]
721 .word 0 # limit 15:0
722 .word 0 # base 15:0
723 .byte 0 # base 23:16
724 .byte 0 # type
725 .byte 0 # limit 19:16, flags
726 .byte 0 # base 31:24
727
728 # linear data segment descriptor
729 .equ LINEAR_SEL, . - GDT_BASE # Selector [0x8]
730 .word 0xFFFF # limit 0xFFFFF
731 .word 0 # base 0
732 .byte 0
733 .byte 0x92 # present, ring 0, data, expand-up, writable
734 .byte 0xCF # page-granular, 32-bit
735 .byte 0
736
737 # linear code segment descriptor
738 .equ LINEAR_CODE_SEL, . - GDT_BASE # Selector [0x10]
739 .word 0xFFFF # limit 0xFFFFF
740 .word 0 # base 0
741 .byte 0
742 .byte 0x9A # present, ring 0, data, expand-up, writable
743 .byte 0xCF # page-granular, 32-bit
744 .byte 0
745
746 # system data segment descriptor
747 .equ SYS_DATA_SEL, . - GDT_BASE # Selector [0x18]
748 .word 0xFFFF # limit 0xFFFFF
749 .word 0 # base 0
750 .byte 0
751 .byte 0x92 # present, ring 0, data, expand-up, writable
752 .byte 0xCF # page-granular, 32-bit
753 .byte 0
754
755 # system code segment descriptor
756 .equ SYS_CODE_SEL, . - GDT_BASE
757 .word 0xFFFF # limit 0xFFFFF
758 .word 0 # base 0
759 .byte 0
760 .byte 0x9A # present, ring 0, data, expand-up, writable
761 .byte 0xCF # page-granular, 32-bit
762 .byte 0
763
764 # spare segment descriptor
765 .equ SYS16_CODE_SEL, . - GDT_BASE
766 .word 0xffff # limit 0xFFFFF
767 .word 0 # base 0
768 .byte 0x0f
769 .byte 0x9b # present, ring 0, data, expand-up, writable
770 .byte 0 # page-granular, 32-bit
771 .byte 0
772
773 # spare segment descriptor
774 .equ SYS16_DATA_SEL, . - GDT_BASE
775 .word 0xffff # limit 0xFFFFF
776 .word 0 # base 0
777 .byte 0
778 .byte 0x93 # present, ring 0, data, expand-up, not-writable
779 .byte 0 # page-granular, 32-bit
780 .byte 0
781
782 # spare segment descriptor
783 .equ SPARE5_SEL, . - GDT_BASE
784 .word 0 # limit 0xFFFFF
785 .word 0 # base 0
786 .byte 0
787 .byte 0 # present, ring 0, data, expand-up, writable
788 .byte 0 # page-granular, 32-bit
789 .byte 0
790 .equ GDT_SIZE, . - GDT_BASE
791
792 #
793 # GDT Descriptor
794 #
795 GdtDesc: # GDT descriptor
796 .word GDT_SIZE - 1
797 .long BootGdtTable
798
799 ProtectedModeEntryLinearAddress:
800 ProtectedModeEntryLinearOffset:
801 .long ProtectedModeEntryPoint
802 .word LINEAR_CODE_SEL