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