1 #------------------------------------------------------------------------------ 2 # 3 # Copyright (c) 2013 - 2016 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_ESRAM_MEM_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 803