]> git.proxmox.com Git - mirror_edk2.git/blob - QuarkPlatformPkg/Library/PlatformSecLib/Ia32/Flat32.S
fbdad53aa0414c2ac3a9b5be4176b5d43cd5b734
[mirror_edk2.git] / QuarkPlatformPkg / Library / PlatformSecLib / Ia32 / Flat32.S
1 #------------------------------------------------------------------------------
2 #
3 # Copyright (c) 2013 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 entry point of the PEI core
306 #
307 movl $0xFFFFFFE0, %edi
308 pushl %ds:(%edi)
309
310 #
311 # Pass BFV into the PEI Core
312 #
313 movl $0xFFFFFFFC, %edi
314 pushl %ds:(%edi)
315
316 #
317 # Pass Temp Ram Base into the PEI Core
318 #
319 movl ASM_PFX(PcdGet32(PcdEsramStage1Base)), %eax
320 addl $(QUARK_ESRAM_MEM_SIZE_BYTES - QUARK_STACK_SIZE_BYTES), %eax
321 pushl %eax
322
323
324 #
325 # Pass stack size into the PEI Core
326 #
327 pushl $QUARK_STACK_SIZE_BYTES
328
329 #
330 # Pass Control into the PEI Core
331 #
332 call SecStartup
333
334 #
335 # PEI Core should never return to here, this is just to capture an invalid return.
336 #
337 jmp .
338
339 #----------------------------------------------------------------------------
340 #
341 # Procedure: stackless_EarlyPlatformInit
342 #
343 # Input: esp - Return address
344 #
345 # Output: None
346 #
347 # Destroys: Assume all registers
348 #
349 # Description:
350 # Any early platform initialisation required
351 #
352 # Return:
353 # None
354 #
355 #----------------------------------------------------------------------------
356 stackless_EarlyPlatformInit:
357
358 #
359 # Save return address
360 #
361 movl %esp, %ebp
362
363 #
364 # Ensure cache is disabled.
365 #
366 movl %cr0, %eax
367 orl $(CR0_CACHE_DISABLE + CR0_NO_WRITE), %eax
368 invd
369 movl %eax, %cr0
370
371 #
372 # Disable NMI operation
373 # Good convention suggests you should read back RTC data port after
374 # accessing the RTC index port.
375 #
376 movb $(NMI_DISABLE), %al
377 movw $(RTC_INDEX), %dx
378 outb %al, %dx
379 movw $(RTC_DATA), %dx
380 inb %dx, %al
381
382 #
383 # Disable SMI (Disables SMI wire, not SMI messages)
384 #
385 movl $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMISC2_OFFSET << SB_ADDR_FIELD)), %ecx
386 leal L1, %esp
387 jmp stackless_SideBand_Read
388 L1:
389 andl $(~SMI_EN), %eax
390 movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMISC2_OFFSET << SB_ADDR_FIELD)), %ecx
391 leal L2, %esp
392 jmp stackless_SideBand_Write
393 L2:
394
395 #
396 # Before we get going, check SOC Unit Registers to see if we are required to issue a warm/cold reset
397 #
398 movl $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGNONSTICKY_W1_OFFSET << SB_ADDR_FIELD)), %ecx
399 leal L3, %esp
400 jmp stackless_SideBand_Read
401 L3:
402 andl $(FORCE_WARM_RESET), %eax
403 jz TestForceColdReset # Zero means bit clear, we're not requested to warm reset so continue as normal
404 jmp IssueWarmReset
405
406 TestForceColdReset:
407 movl $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGNONSTICKY_W1_OFFSET << SB_ADDR_FIELD)), %ecx
408 leal L4, %esp
409 jmp stackless_SideBand_Read
410 L4:
411 andl $(FORCE_COLD_RESET), %eax
412 jz TestHmboundLock # Zero means bit clear, we're not requested to cold reset so continue as normal
413 jmp IssueColdReset
414
415 #
416 # Before setting HMBOUND, check it's not locked
417 #
418 TestHmboundLock:
419 movl $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMBOUND_OFFSET << SB_ADDR_FIELD)), %ecx
420 leal L5, %esp
421 jmp stackless_SideBand_Read
422 L5:
423 andl $(HMBOUND_LOCK), %eax
424 jz ConfigHmbound # Zero means bit clear, we have the config we want so continue as normal
425 #
426 # Failed to config - store sticky bit debug
427 #
428 movl $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx
429 leal L6, %esp
430 jmp stackless_SideBand_Read
431 L6:
432 orl $(RESET_FOR_HMBOUND_LOCK), %eax
433 movl $((OPCODE_SIDEBAND_ALT_REG_WRITE << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx
434 leal L7, %esp
435 jmp stackless_SideBand_Write
436 L7:
437 jmp IssueWarmReset
438
439 #
440 # Set up the HMBOUND register
441 #
442 ConfigHmbound:
443 movl $(HMBOUND_ADDRESS), %eax # Data (Set HMBOUND location)
444 movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HMBOUND_OFFSET << SB_ADDR_FIELD)), %ecx
445 leal L8, %esp
446 jmp stackless_SideBand_Write
447 L8:
448
449 #
450 # Enable interrupts to Remote Management Unit when a IMR/SMM/HMBOUND violation occurs.
451 #
452 movl $(ENABLE_IMR_INTERRUPT), %eax # Data (Set interrupt enable mask)
453 movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (MEMORY_MANAGER_PORT_ID << SB_PORT_FIELD) | (BIMRVCTL_OFFSET << SB_ADDR_FIELD)), %ecx
454 leal L9, %esp
455 jmp stackless_SideBand_Write
456 L9:
457
458 #
459 # Set eSRAM address
460 #
461 movl ASM_PFX(PcdGet32(PcdEsramStage1Base)), %eax # Data (Set eSRAM location)
462 shr $(0x18), %eax
463 addl $(BLOCK_ENABLE_PG), %eax
464 movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (MEMORY_MANAGER_PORT_ID << SB_PORT_FIELD) | (ESRAMPGCTRL_BLOCK_OFFSET << SB_ADDR_FIELD)), %ecx
465 leal L10, %esp
466 jmp stackless_SideBand_Write
467 L10:
468
469 #
470 # Check that we're not blocked from setting the config that we want.
471 #
472 movl $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (MEMORY_MANAGER_PORT_ID << SB_PORT_FIELD) | (ESRAMPGCTRL_BLOCK_OFFSET << SB_ADDR_FIELD)), %ecx
473 leal L11, %esp
474 jmp stackless_SideBand_Read
475 L11:
476 andl $(BLOCK_ENABLE_PG), %eax
477 jnz ConfigPci # Non-zero means bit set, we have the config we want so continue as normal
478 #
479 # Failed to config - store sticky bit debug
480 #
481 movl $((OPCODE_SIDEBAND_ALT_REG_READ << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx
482 leal L12, %esp
483 jmp stackless_SideBand_Read
484 L12:
485 orl $(RESET_FOR_ESRAM_LOCK), %eax # Set the bit we're interested in
486 movl $((OPCODE_SIDEBAND_ALT_REG_WRITE << SB_OPCODE_FIELD) | (SOC_UNIT_PORT_ID << SB_PORT_FIELD) | (CFGSTICKY_RW_OFFSET << SB_ADDR_FIELD)), %ecx
487 leal L13, %esp
488 jmp stackless_SideBand_Write
489 L13:
490 jmp IssueWarmReset
491
492 #
493 # Enable PCIEXBAR
494 #
495 ConfigPci:
496 movl $(EC_BASE + EC_ENABLE), %eax # Data
497 movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (MEMORY_ARBITER_PORT_ID << SB_PORT_FIELD) | (AEC_CTRL_OFFSET << SB_ADDR_FIELD)), %ecx
498 leal L14, %esp
499 jmp stackless_SideBand_Write
500 L14:
501
502 movl $(EC_BASE + EC_ENABLE), %eax # Data
503 movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HECREG_OFFSET << SB_ADDR_FIELD)), %ecx
504 leal L15, %esp
505 jmp stackless_SideBand_Write
506 L15:
507
508 #
509 # Open up full 8MB SPI decode
510 #
511 movl $(PCI_CFG | (ILB_PFA << 8) | BDE), %ebx # PCI Configuration address
512 movl $(DECODE_ALL_REGIONS_ENABLE), %eax
513 leal L16, %esp
514 jmp stackless_PCIConfig_Write
515 L16:
516
517 #
518 # Enable NMI operation
519 # Good convention suggests you should read back RTC data port after
520 # accessing the RTC index port.
521 #
522 movb $(NMI_ENABLE), %al
523 movw $(RTC_INDEX), %dx
524 outb %al, %dx
525 movw $(RTC_DATA), %dx
526 inb %dx, %al
527
528 #
529 # Clear Host Bridge SMI, NMI, INTR fields
530 #
531 movl $((OPCODE_SIDEBAND_REG_READ << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HLEGACY_OFFSET << SB_ADDR_FIELD)), %ecx
532 leal L21, %esp
533 jmp stackless_SideBand_Read
534 L21:
535 andl $~(NMI + SMI + INTR), %eax # Clear NMI, SMI, INTR fields
536 movl $((OPCODE_SIDEBAND_REG_WRITE << SB_OPCODE_FIELD) | (HOST_BRIDGE_PORT_ID << SB_PORT_FIELD) | (HLEGACY_OFFSET << SB_ADDR_FIELD)), %ecx
537 leal L22, %esp
538 jmp stackless_SideBand_Write
539 L22:
540
541 #
542 # Restore return address
543 #
544 movl %ebp, %esp
545 RET32
546
547 IssueWarmReset:
548 #
549 # Issue Warm Reset request to Remote Management Unit via iLB
550 #
551 movw $(CF9_WARM_RESET), %ax
552 movw $(ILB_RESET_REG), %dx
553 outw %ax, %dx
554 jmp . # Stay here until we are reset.
555
556 IssueColdReset:
557 #
558 # Issue Cold Reset request to Remote Management Unit via iLB
559 #
560 movw $(CF9_COLD_RESET), %ax
561 movw $(ILB_RESET_REG), %dx
562 outw %ax, %dx
563 jmp . # Stay here until we are reset.
564
565 #----------------------------------------------------------------------------
566 #
567 # Procedure: stackless_SideBand_Read
568 #
569 # Input: esp - return address
570 # ecx[15:8] - Register offset
571 # ecx[23:16] - Port ID
572 # ecx[31:24] - Opcode
573 #
574 # Output: eax - Data read
575 #
576 # Destroys:
577 # eax
578 # ebx
579 # cl
580 # esi
581 #
582 # Description:
583 # Perform requested sideband read
584 #
585 #----------------------------------------------------------------------------
586 stackless_SideBand_Read:
587
588 movl %esp, %esi # Save the return address
589
590 #
591 # Load the SideBand Packet Register to generate the transaction
592 #
593 movl $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_BUS_CONTROL_REG)), %ebx # PCI Configuration address
594 movb $(ALL_BYTE_EN << SB_BE_FIELD), %cl # Set all Byte Enable bits
595 xchgl %ecx, %eax
596 leal L17, %esp
597 jmp stackless_PCIConfig_Write
598 L17:
599 xchgl %ecx, %eax
600
601 #
602 # Read the SideBand Data Register
603 #
604 movl $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_DATA_REG)), %ebx # PCI Configuration address
605 leal L18, %esp
606 jmp stackless_PCIConfig_Read
607 L18:
608
609 movl %esi, %esp # Restore the return address
610 RET32
611
612
613 #----------------------------------------------------------------------------
614 #
615 # Procedure: stackless_SideBand_Write
616 #
617 # Input: esp - return address
618 # eax - Data
619 # ecx[15:8] - Register offset
620 # ecx[23:16] - Port ID
621 # ecx[31:24] - Opcode
622 #
623 # Output: None
624 #
625 # Destroys:
626 # ebx
627 # cl
628 # esi
629 #
630 # Description:
631 # Perform requested sideband write
632 #
633 #
634 #----------------------------------------------------------------------------
635 stackless_SideBand_Write:
636
637 movl %esp, %esi # Save the return address
638
639 #
640 # Load the SideBand Data Register with the data
641 #
642 movl $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_DATA_REG)), %ebx # PCI Configuration address
643 leal L19, %esp
644 jmp stackless_PCIConfig_Write
645 L19:
646
647 #
648 # Load the SideBand Packet Register to generate the transaction
649 #
650 movl $((PCI_CFG) | (HOST_BRIDGE_PFA << 8) | (MESSAGE_BUS_CONTROL_REG)), %ebx # PCI Configuration address
651 movb $(ALL_BYTE_EN << SB_BE_FIELD), %cl # Set all Byte Enable bits
652 xchgl %ecx, %eax
653 leal L20, %esp
654 jmp stackless_PCIConfig_Write
655 L20:
656 xchgl %ecx, %eax
657
658 movl %esi, %esp # Restore the return address
659 RET32
660
661
662 #----------------------------------------------------------------------------
663 #
664 # Procedure: stackless_PCIConfig_Write
665 #
666 # Input: esp - return address
667 # eax - Data to write
668 # ebx - PCI Config Address
669 #
670 # Output: None
671 #
672 # Destroys:
673 # dx
674 #
675 # Description:
676 # Perform a DWORD PCI Configuration write
677 #
678 #----------------------------------------------------------------------------
679 stackless_PCIConfig_Write:
680
681 #
682 # Write the PCI Config Address to the address port
683 #
684 xchgl %ebx, %eax
685 movw $(PCI_ADDRESS_PORT), %dx
686 outl %eax, %dx
687 xchgl %ebx, %eax
688
689 #
690 # Write the PCI DWORD Data to the data port
691 #
692 movw $(PCI_DATA_PORT), %dx
693 outl %eax, %dx
694
695 RET32
696
697
698 #----------------------------------------------------------------------------
699 #
700 # Procedure: stackless_PCIConfig_Read
701 #
702 # Input: esp - return address
703 # ebx - PCI Config Address
704 #
705 # Output: eax - Data read
706 #
707 # Destroys:
708 # eax
709 # dx
710 #
711 # Description:
712 # Perform a DWORD PCI Configuration read
713 #
714 #----------------------------------------------------------------------------
715 stackless_PCIConfig_Read:
716
717 #
718 # Write the PCI Config Address to the address port
719 #
720 xchgl %ebx, %eax
721 movw $(PCI_ADDRESS_PORT), %dx
722 outl %eax, %dx
723 xchgl %ebx, %eax
724
725 #
726 # Read the PCI DWORD Data from the data port
727 #
728 movw $(PCI_DATA_PORT), %dx
729 inl %dx, %eax
730
731 RET32
732
733
734 #
735 # ROM-based Global-Descriptor Table for the Tiano PEI Phase
736 #
737 .align 16
738 #
739 # GDT[0]: 000h: Null entry, never used.
740 #
741
742 GDT_BASE:
743 BootGdtTable:
744 # null descriptor
745 .equ NULL_SEL, . - GDT_BASE # Selector [0]
746 .word 0 # limit 15:0
747 .word 0 # base 15:0
748 .byte 0 # base 23:16
749 .byte 0 # type
750 .byte 0 # limit 19:16, flags
751 .byte 0 # base 31:24
752
753 # linear data segment descriptor
754 .equ LINEAR_SEL, . - GDT_BASE # Selector [0x8]
755 .word 0xFFFF # limit 0xFFFFF
756 .word 0 # base 0
757 .byte 0
758 .byte 0x92 # present, ring 0, data, expand-up, writable
759 .byte 0xCF # page-granular, 32-bit
760 .byte 0
761
762 # linear code segment descriptor
763 .equ LINEAR_CODE_SEL, . - GDT_BASE # Selector [0x10]
764 .word 0xFFFF # limit 0xFFFFF
765 .word 0 # base 0
766 .byte 0
767 .byte 0x9A # present, ring 0, data, expand-up, writable
768 .byte 0xCF # page-granular, 32-bit
769 .byte 0
770
771 # system data segment descriptor
772 .equ SYS_DATA_SEL, . - GDT_BASE # Selector [0x18]
773 .word 0xFFFF # limit 0xFFFFF
774 .word 0 # base 0
775 .byte 0
776 .byte 0x92 # present, ring 0, data, expand-up, writable
777 .byte 0xCF # page-granular, 32-bit
778 .byte 0
779
780 # system code segment descriptor
781 .equ SYS_CODE_SEL, . - GDT_BASE
782 .word 0xFFFF # limit 0xFFFFF
783 .word 0 # base 0
784 .byte 0
785 .byte 0x9A # present, ring 0, data, expand-up, writable
786 .byte 0xCF # page-granular, 32-bit
787 .byte 0
788
789 # spare segment descriptor
790 .equ SYS16_CODE_SEL, . - GDT_BASE
791 .word 0xffff # limit 0xFFFFF
792 .word 0 # base 0
793 .byte 0x0f
794 .byte 0x9b # present, ring 0, data, expand-up, writable
795 .byte 0 # page-granular, 32-bit
796 .byte 0
797
798 # spare segment descriptor
799 .equ SYS16_DATA_SEL, . - GDT_BASE
800 .word 0xffff # limit 0xFFFFF
801 .word 0 # base 0
802 .byte 0
803 .byte 0x93 # present, ring 0, data, expand-up, not-writable
804 .byte 0 # page-granular, 32-bit
805 .byte 0
806
807 # spare segment descriptor
808 .equ SPARE5_SEL, . - GDT_BASE
809 .word 0 # limit 0xFFFFF
810 .word 0 # base 0
811 .byte 0
812 .byte 0 # present, ring 0, data, expand-up, writable
813 .byte 0 # page-granular, 32-bit
814 .byte 0
815 .equ GDT_SIZE, . - GDT_BASE
816
817 #
818 # GDT Descriptor
819 #
820 GdtDesc: # GDT descriptor
821 .word GDT_SIZE - 1
822 .long BootGdtTable
823
824 ProtectedModeEntryLinearAddress:
825 ProtectedModeEntryLinearOffset:
826 .long ProtectedModeEntryPoint
827 .word LINEAR_CODE_SEL