]> git.proxmox.com Git - mirror_edk2.git/blobdiff - QuarkPlatformPkg/Library/PlatformSecLib/Ia32/Flat32.asm
QuarkPlatformPkg: Add new package for Galileo boards
[mirror_edk2.git] / QuarkPlatformPkg / Library / PlatformSecLib / Ia32 / Flat32.asm
diff --git a/QuarkPlatformPkg/Library/PlatformSecLib/Ia32/Flat32.asm b/QuarkPlatformPkg/Library/PlatformSecLib/Ia32/Flat32.asm
new file mode 100644 (file)
index 0000000..3c6050d
--- /dev/null
@@ -0,0 +1,691 @@
+;------------------------------------------------------------------------------\r
+;\r
+; Copyright (c) 2013-2015 Intel Corporation.\r
+;\r
+; This program and the accompanying materials\r
+; are licensed and made available under the terms and conditions of the BSD License\r
+; which accompanies this distribution.  The full text of the license may be found at\r
+; http://opensource.org/licenses/bsd-license.php\r
+;\r
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+;\r
+; Module Name:\r
+;\r
+;  Flat32.asm\r
+;\r
+; Abstract:\r
+;\r
+;  This is the code that goes from real-mode to protected mode.\r
+;  It consumes the reset vector, configures the stack.\r
+;\r
+;\r
+;------------------------------------------------------------------------------\r
+\r
+\r
+;\r
+; Define assembler characteristics\r
+;\r
+.586p\r
+.model flat, c\r
+\r
+;\r
+; Include processor definitions\r
+;\r
+\r
+INCLUDE Platform.inc\r
+\r
+\r
+;\r
+; CR0 cache control bit definition\r
+;\r
+CR0_CACHE_DISABLE       EQU 040000000h\r
+CR0_NO_WRITE            EQU 020000000h\r
+\r
+;\r
+; External and public declarations\r
+;  TopOfStack is used by C code\r
+;  SecStartup is the entry point to the C code\r
+; Neither of these names can be modified without\r
+; updating the C code.\r
+;\r
+EXTRN   PlatformSecLibStartup: NEAR\r
+EXTERNDEF   C   PcdGet32 (PcdEsramStage1Base):DWORD\r
+\r
+;\r
+; Contrary to the name, this file contains 16 bit code as well.\r
+;\r
+_TEXT_REALMODE      SEGMENT PARA PUBLIC USE16 'CODE'\r
+                    ASSUME  CS:_TEXT_REALMODE, DS:_TEXT_REALMODE\r
+\r
+;----------------------------------------------------------------------------\r
+;\r
+; Procedure:    _ModuleEntryPoint\r
+;\r
+; Input:        None\r
+;\r
+; Output:       None\r
+;\r
+; Destroys:     Assume all registers\r
+;\r
+; Description:\r
+;\r
+;   Transition to non-paged flat-model protected mode from a\r
+;   hard-coded GDT that provides exactly two descriptors.\r
+;   This is a bare bones transition to protected mode only\r
+;   used for a while in PEI and possibly DXE.\r
+;\r
+;   After enabling protected mode, a far jump is executed to\r
+;   transfer to PEI using the newly loaded GDT.\r
+;\r
+; Return:       None\r
+;\r
+;----------------------------------------------------------------------------\r
+align 16\r
+_ModuleEntryPoint      PROC C PUBLIC\r
+\r
+  ;\r
+  ; Warm Reset (INIT#) check.\r
+  ;\r
+  mov     si, 0F000h\r
+  mov     ds, si\r
+  mov     si, 0FFF0h\r
+  cmp     BYTE PTR [si], 0EAh   ; Is it warm reset ?\r
+  jne     NotWarmReset          ; JIf not.\r
+\r
+  mov     al, 08\r
+  mov     dx, 0cf9h\r
+  out     dx, al\r
+  mov     al, 055h\r
+  out     080h, al;\r
+  jmp $\r
+NotWarmReset:\r
+\r
+  ;\r
+  ; Load the GDT table in GdtDesc\r
+  ;\r
+  mov     esi, OFFSET GdtDesc\r
+  db      66h\r
+  lgdt    fword ptr cs:[si]\r
+\r
+  ;\r
+  ; Transition to 16 bit protected mode\r
+  ;\r
+  mov     eax, cr0                   ; Get control register 0\r
+  or      eax, 00000003h             ; Set PE bit (bit #0) & MP bit (bit #1)\r
+  mov     cr0, eax                   ; Activate protected mode\r
+\r
+  ;\r
+  ; Now we're in 16 bit protected mode\r
+  ; Set up the selectors for 32 bit protected mode entry\r
+  ;\r
+  mov     ax, SYS_DATA_SEL\r
+  mov     ds, ax\r
+  mov     es, ax\r
+  mov     fs, ax\r
+  mov     gs, ax\r
+  mov     ss, ax\r
+\r
+  ;\r
+  ; Transition to Flat 32 bit protected mode\r
+  ; The jump to a far pointer causes the transition to 32 bit mode\r
+  ;\r
+  mov esi, offset ProtectedModeEntryLinearAddress\r
+  jmp     fword ptr cs:[si]\r
+\r
+_ModuleEntryPoint   ENDP\r
+\r
+_TEXT_REALMODE      ENDS\r
+\r
+.code\r
+;\r
+; Protected mode portion initializes stack, configures cache, and calls C entry point\r
+;\r
+\r
+;----------------------------------------------------------------------------\r
+;\r
+; Procedure:    ProtectedModeEntryPoint\r
+;\r
+; Input:        Executing in 32 Bit Protected (flat) mode\r
+;                cs: 0-4GB\r
+;                ds: 0-4GB\r
+;                es: 0-4GB\r
+;                fs: 0-4GB\r
+;                gs: 0-4GB\r
+;                ss: 0-4GB\r
+;\r
+; Output:       This function never returns\r
+;\r
+; Destroys:\r
+;               ecx\r
+;               edi\r
+;                esi\r
+;                esp\r
+;\r
+; Description:\r
+;                Perform any essential early platform initilaisation\r
+;               Setup a stack\r
+;               Call the main EDKII Sec C code\r
+;\r
+;----------------------------------------------------------------------------\r
+\r
+ProtectedModeEntryPoint PROC NEAR C PUBLIC\r
+\r
+  JMP32  stackless_EarlyPlatformInit\r
+\r
+  ;\r
+  ; Set up stack pointer\r
+  ;\r
+  mov     esp, PcdGet32(PcdEsramStage1Base)\r
+  mov     esi, QUARK_ESRAM_MEM_SIZE_BYTES\r
+  add     esp, esi                         ; ESP = top of stack (stack grows downwards).\r
+\r
+  ;\r
+  ; Store the the BIST value in EBP\r
+  ;\r
+  mov     ebp, 00h        ; No processor BIST on Quark\r
+\r
+  ;\r
+  ; Push processor count to stack first, then BIST status (AP then BSP)\r
+  ;\r
+  mov     eax, 1\r
+  cpuid\r
+  shr     ebx, 16\r
+  and     ebx, 0000000FFh\r
+  cmp     bl, 1\r
+  jae     PushProcessorCount\r
+\r
+  ;\r
+  ; Some processors report 0 logical processors.  Effectively 0 = 1.\r
+  ; So we fix up the processor count\r
+  ;\r
+  inc     ebx\r
+\r
+PushProcessorCount:\r
+  push    ebx\r
+\r
+  ;\r
+  ; We need to implement a long-term solution for BIST capture.  For now, we just copy BSP BIST\r
+  ; for all processor threads\r
+  ;\r
+  xor     ecx, ecx\r
+  mov     cl, bl\r
+PushBist:\r
+  push    ebp\r
+  loop    PushBist\r
+\r
+  ;\r
+  ; Pass Control into the PEI Core\r
+  ;\r
+  call PlatformSecLibStartup\r
+\r
+  ;\r
+  ; PEI Core should never return to here, this is just to capture an invalid return.\r
+  ;\r
+  jmp     $\r
+\r
+ProtectedModeEntryPoint ENDP\r
+\r
+;----------------------------------------------------------------------------\r
+;\r
+; Procedure:    stackless_EarlyPlatformInit\r
+;\r
+; Input:        esp - Return address\r
+;\r
+; Output:       None\r
+;\r
+; Destroys:\r
+;                eax\r
+;                ecx\r
+;                dx\r
+;                ebp\r
+;\r
+; Description:\r
+;        Any essential early platform initialisation required:\r
+;        (1) Disable Cache\r
+;        (2) Disable NMI's/SMI's\r
+;        (3) Setup HMBOUND (defines what memory accesses go to MMIO/RAM)\r
+;        (4) Setup eSRAM (provide early memory to the system)\r
+;        (5) Setup PCIEXBAR access mechanism\r
+;        (6) Open up full SPI flash decode\r
+;\r
+;----------------------------------------------------------------------------\r
+stackless_EarlyPlatformInit  PROC NEAR C PUBLIC\r
+\r
+  ;\r
+  ; Save return address\r
+  ;\r
+  mov  ebp, esp\r
+\r
+  ;\r
+  ; Ensure cache is disabled.\r
+  ;\r
+  mov     eax, cr0\r
+  or      eax, CR0_CACHE_DISABLE + CR0_NO_WRITE\r
+  invd\r
+  mov     cr0, eax\r
+\r
+  ;\r
+  ; Disable NMI\r
+  ; Good convention suggests you should read back RTC data port after\r
+  ; accessing the RTC index port.\r
+  ;\r
+  mov  al, NMI_DISABLE\r
+  mov  dx, RTC_INDEX\r
+  out  dx, al\r
+  mov  dx, RTC_DATA\r
+  in  al, dx\r
+\r
+  ;\r
+  ; Disable SMI (Disables SMI wire, not SMI messages)\r
+  ;\r
+  mov  ecx, (OPCODE_SIDEBAND_REG_READ SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HMISC2_OFFSET SHL SB_ADDR_FIELD)\r
+  JMP32  stackless_SideBand_Read\r
+  and  eax, NOT (SMI_EN)\r
+  mov  ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HMISC2_OFFSET SHL SB_ADDR_FIELD)\r
+  JMP32  stackless_SideBand_Write\r
+\r
+  ;\r
+  ; Before we get going, check SOC Unit Registers to see if we are required to issue a warm/cold reset\r
+  ;\r
+  mov  ecx, (OPCODE_SIDEBAND_ALT_REG_READ SHL SB_OPCODE_FIELD) OR (SOC_UNIT_PORT_ID SHL SB_PORT_FIELD) OR (CFGNONSTICKY_W1_OFFSET SHL SB_ADDR_FIELD)\r
+  JMP32  stackless_SideBand_Read\r
+  and  eax, FORCE_WARM_RESET\r
+  jz TestForceColdReset    ; Zero means bit clear, we're not requested to warm reset so continue as normal\r
+  jmp IssueWarmReset\r
+\r
+TestForceColdReset:\r
+  mov  ecx, (OPCODE_SIDEBAND_ALT_REG_READ SHL SB_OPCODE_FIELD) OR (SOC_UNIT_PORT_ID SHL SB_PORT_FIELD) OR (CFGSTICKY_W1_OFFSET SHL SB_ADDR_FIELD)\r
+  JMP32  stackless_SideBand_Read\r
+  and  eax, FORCE_COLD_RESET\r
+  jz TestHmboundLock    ; Zero means bit clear, we're not requested to cold reset so continue as normal\r
+  jmp IssueColdReset\r
+\r
+  ;\r
+  ; Before setting HMBOUND, check it's not locked\r
+  ;\r
+TestHmboundLock:\r
+  mov  ecx, (OPCODE_SIDEBAND_REG_READ SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HMBOUND_OFFSET SHL SB_ADDR_FIELD)\r
+  JMP32  stackless_SideBand_Read\r
+  and  eax, HMBOUND_LOCK\r
+  jz ConfigHmbound  ; Zero means bit clear, we have the config we want so continue as normal\r
+  ;\r
+  ; Failed to config - store sticky bit debug\r
+  ;\r
+  mov  ecx, (OPCODE_SIDEBAND_ALT_REG_READ SHL SB_OPCODE_FIELD) OR (SOC_UNIT_PORT_ID SHL SB_PORT_FIELD) OR (CFGSTICKY_RW_OFFSET SHL SB_ADDR_FIELD)\r
+  JMP32  stackless_SideBand_Read\r
+  or  eax, RESET_FOR_HMBOUND_LOCK  ; Set the bit we're interested in\r
+  mov  ecx, (OPCODE_SIDEBAND_ALT_REG_WRITE SHL SB_OPCODE_FIELD) OR (SOC_UNIT_PORT_ID SHL SB_PORT_FIELD) OR (CFGSTICKY_RW_OFFSET SHL SB_ADDR_FIELD)\r
+  JMP32  stackless_SideBand_Write\r
+  jmp IssueWarmReset\r
+\r
+  ;\r
+  ; Set up the HMBOUND register\r
+  ;\r
+ConfigHmbound:\r
+  mov  eax, HMBOUND_ADDRESS    ; Data (Set HMBOUND location)\r
+  mov  ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HMBOUND_OFFSET SHL SB_ADDR_FIELD)\r
+  JMP32  stackless_SideBand_Write\r
+\r
+  ;\r
+  ; Enable interrupts to Remote Management Unit when a IMR/SMM/HMBOUND violation occurs.\r
+  ;\r
+  mov  eax, ENABLE_IMR_INTERRUPT        ; Data (Set interrupt enable mask)\r
+  mov  ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (MEMORY_MANAGER_PORT_ID SHL SB_PORT_FIELD) OR (BIMRVCTL_OFFSET SHL SB_ADDR_FIELD)\r
+  JMP32  stackless_SideBand_Write\r
+\r
+  ;\r
+  ; Set eSRAM address\r
+  ;\r
+  mov  eax, PcdGet32 (PcdEsramStage1Base)        ; Data (Set eSRAM location)\r
+  shr  eax, 18h        ; Data (Set eSRAM location)\r
+  add eax, BLOCK_ENABLE_PG\r
+  mov  ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (MEMORY_MANAGER_PORT_ID SHL SB_PORT_FIELD) OR (ESRAMPGCTRL_BLOCK_OFFSET SHL SB_ADDR_FIELD)\r
+  JMP32  stackless_SideBand_Write\r
+  ;\r
+  ; Check that we're not blocked from setting the config that we want.\r
+  ;\r
+  mov  ecx, (OPCODE_SIDEBAND_REG_READ SHL SB_OPCODE_FIELD) OR (MEMORY_MANAGER_PORT_ID SHL SB_PORT_FIELD) OR (ESRAMPGCTRL_BLOCK_OFFSET SHL SB_ADDR_FIELD)\r
+  JMP32  stackless_SideBand_Read\r
+  and  eax, BLOCK_ENABLE_PG\r
+  jnz ConfigPci  ; Non-zero means bit set, we have the config we want so continue as normal\r
+  ;\r
+  ; Failed to config - store sticky bit debug\r
+  ;\r
+  mov  ecx, (OPCODE_SIDEBAND_ALT_REG_READ SHL SB_OPCODE_FIELD) OR (SOC_UNIT_PORT_ID SHL SB_PORT_FIELD) OR (CFGSTICKY_RW_OFFSET SHL SB_ADDR_FIELD)\r
+  JMP32  stackless_SideBand_Read\r
+  or  eax, RESET_FOR_ESRAM_LOCK  ; Set the bit we're interested in\r
+  mov  ecx, (OPCODE_SIDEBAND_ALT_REG_WRITE SHL SB_OPCODE_FIELD) OR (SOC_UNIT_PORT_ID SHL SB_PORT_FIELD) OR (CFGSTICKY_RW_OFFSET SHL SB_ADDR_FIELD)\r
+  JMP32  stackless_SideBand_Write\r
+  jmp IssueWarmReset\r
+\r
+  ;\r
+  ; Enable PCIEXBAR\r
+  ;\r
+ConfigPci:\r
+  mov  eax, (EC_BASE + EC_ENABLE)      ; Data\r
+  mov  ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (MEMORY_ARBITER_PORT_ID SHL SB_PORT_FIELD) OR (AEC_CTRL_OFFSET SHL SB_ADDR_FIELD)\r
+  JMP32  stackless_SideBand_Write\r
+\r
+  mov  eax, (EC_BASE + EC_ENABLE)      ; Data\r
+  mov  ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HECREG_OFFSET SHL SB_ADDR_FIELD)\r
+  JMP32  stackless_SideBand_Write\r
+\r
+  ;\r
+  ;  Open up full 8MB SPI decode\r
+  ;\r
+  mov  ebx, PCI_CFG OR (ILB_PFA SHL 8) OR BDE  ; PCI Configuration address\r
+  mov eax, DECODE_ALL_REGIONS_ENABLE\r
+  JMP32  stackless_PCIConfig_Write\r
+\r
+  ;\r
+  ; Enable NMI operation\r
+  ; Good convention suggests you should read back RTC data port after\r
+  ; accessing the RTC index port.\r
+  ;\r
+  mov al, NMI_ENABLE\r
+  mov dx, RTC_INDEX\r
+  out dx, al\r
+  mov dx, RTC_DATA\r
+  in  al, dx\r
+\r
+  ;\r
+  ; Clear Host Bridge SMI, NMI, INTR fields\r
+  ;\r
+  mov  ecx, (OPCODE_SIDEBAND_REG_READ SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HLEGACY_OFFSET SHL SB_ADDR_FIELD)\r
+  JMP32  stackless_SideBand_Read\r
+  and  eax, NOT(NMI + SMI + INTR)  ; Clear NMI, SMI, INTR fields\r
+  mov  ecx, (OPCODE_SIDEBAND_REG_WRITE SHL SB_OPCODE_FIELD) OR (HOST_BRIDGE_PORT_ID SHL SB_PORT_FIELD) OR (HLEGACY_OFFSET SHL SB_ADDR_FIELD)\r
+  JMP32  stackless_SideBand_Write\r
+\r
+  ;\r
+  ; Restore return address\r
+  ;\r
+  mov  esp, ebp\r
+  RET32\r
+\r
+IssueWarmReset:\r
+  ;\r
+  ; Issue Warm Reset request to Remote Management Unit via iLB\r
+  ;\r
+  mov ax, CF9_WARM_RESET\r
+  mov  dx, ILB_RESET_REG\r
+  out  dx, ax\r
+  jmp  $  ; Stay here until we are reset.\r
+\r
+IssueColdReset:\r
+  ;\r
+  ; Issue Cold Reset request to Remote Management Unit via iLB\r
+  ;\r
+  mov ax, CF9_COLD_RESET\r
+  mov  dx, ILB_RESET_REG\r
+  out  dx, ax\r
+  jmp  $  ; Stay here until we are reset.\r
+\r
+stackless_EarlyPlatformInit ENDP\r
+\r
+;----------------------------------------------------------------------------\r
+;\r
+; Procedure:    stackless_SideBand_Read\r
+;\r
+; Input:        esp - return address\r
+;                ecx[15:8] - Register offset\r
+;                ecx[23:16] - Port ID\r
+;                ecx[31:24] - Opcode\r
+;\r
+; Output:       eax - Data read\r
+;\r
+; Destroys:\r
+;                eax\r
+;                ebx\r
+;                cl\r
+;                esi\r
+;\r
+; Description:\r
+;        Perform requested sideband read\r
+;\r
+;----------------------------------------------------------------------------\r
+stackless_SideBand_Read  PROC NEAR C PUBLIC\r
+\r
+  mov  esi, esp        ; Save the return address\r
+\r
+  ;\r
+  ; Load the SideBand Packet Register to generate the transaction\r
+  ;\r
+  mov  ebx, PCI_CFG OR (HOST_BRIDGE_PFA SHL 8) OR MESSAGE_BUS_CONTROL_REG  ; PCI Configuration address\r
+  mov  cl, (ALL_BYTE_EN SHL SB_BE_FIELD)    ; Set all Byte Enable bits\r
+  xchg  eax, ecx\r
+  JMP32  stackless_PCIConfig_Write\r
+  xchg  eax, ecx\r
+\r
+  ;\r
+  ; Read the SideBand Data Register\r
+  ;\r
+  mov  ebx, PCI_CFG OR (HOST_BRIDGE_PFA SHL 8) OR MESSAGE_DATA_REG    ; PCI Configuration address\r
+  JMP32  stackless_PCIConfig_Read\r
+\r
+  mov  esp, esi        ; Restore the return address\r
+  RET32\r
+\r
+stackless_SideBand_Read ENDP\r
+\r
+;----------------------------------------------------------------------------\r
+;\r
+; Procedure:    stackless_SideBand_Write\r
+;\r
+; Input:        esp - return address\r
+;                eax - Data\r
+;                ecx[15:8] - Register offset\r
+;                ecx[23:16] - Port ID\r
+;                ecx[31:24] - Opcode\r
+;\r
+; Output:       None\r
+;\r
+; Destroys:\r
+;                ebx\r
+;                cl\r
+;                esi\r
+;\r
+; Description:\r
+;        Perform requested sideband write\r
+;\r
+;\r
+;----------------------------------------------------------------------------\r
+stackless_SideBand_Write  PROC NEAR C PUBLIC\r
+\r
+  mov  esi, esp        ; Save the return address\r
+\r
+  ;\r
+  ; Load the SideBand Data Register with the data\r
+  ;\r
+  mov  ebx, PCI_CFG OR (HOST_BRIDGE_PFA SHL 8) OR MESSAGE_DATA_REG  ; PCI Configuration address\r
+  JMP32  stackless_PCIConfig_Write\r
+\r
+  ;\r
+  ; Load the SideBand Packet Register to generate the transaction\r
+  ;\r
+  mov  ebx, PCI_CFG OR (HOST_BRIDGE_PFA SHL 8) OR MESSAGE_BUS_CONTROL_REG  ; PCI Configuration address\r
+  mov  cl, (ALL_BYTE_EN SHL SB_BE_FIELD)    ; Set all Byte Enable bits\r
+  xchg  eax, ecx\r
+  JMP32  stackless_PCIConfig_Write\r
+  xchg  eax, ecx\r
+\r
+  mov  esp, esi        ; Restore the return address\r
+  RET32\r
+\r
+stackless_SideBand_Write ENDP\r
+\r
+;----------------------------------------------------------------------------\r
+;\r
+; Procedure:    stackless_PCIConfig_Write\r
+;\r
+; Input:        esp - return address\r
+;                eax - Data to write\r
+;                ebx - PCI Config Address\r
+;\r
+; Output:       None\r
+;\r
+; Destroys:\r
+;                dx\r
+;\r
+; Description:\r
+;        Perform a DWORD PCI Configuration write\r
+;\r
+;----------------------------------------------------------------------------\r
+stackless_PCIConfig_Write  PROC NEAR C PUBLIC\r
+\r
+  ;\r
+  ; Write the PCI Config Address to the address port\r
+  ;\r
+  xchg  eax, ebx\r
+  mov  dx, PCI_ADDRESS_PORT\r
+  out  dx, eax\r
+  xchg  eax, ebx\r
+\r
+  ;\r
+  ; Write the PCI DWORD Data to the data port\r
+  ;\r
+  mov  dx, PCI_DATA_PORT\r
+  out  dx, eax\r
+\r
+  RET32\r
+\r
+stackless_PCIConfig_Write ENDP\r
+\r
+;----------------------------------------------------------------------------\r
+;\r
+; Procedure:    stackless_PCIConfig_Read\r
+;\r
+; Input:        esp - return address\r
+;                ebx - PCI Config Address\r
+;\r
+; Output:       eax - Data read\r
+;\r
+; Destroys:\r
+;                eax\r
+;                dx\r
+;\r
+; Description:\r
+;        Perform a DWORD PCI Configuration read\r
+;\r
+;----------------------------------------------------------------------------\r
+stackless_PCIConfig_Read  PROC NEAR C PUBLIC\r
+\r
+  ;\r
+  ; Write the PCI Config Address to the address port\r
+  ;\r
+  xchg  eax, ebx\r
+  mov  dx, PCI_ADDRESS_PORT\r
+  out  dx, eax\r
+  xchg  eax, ebx\r
+\r
+  ;\r
+  ; Read the PCI DWORD Data from the data port\r
+  ;\r
+  mov  dx, PCI_DATA_PORT\r
+  in  eax, dx\r
+\r
+  RET32\r
+\r
+stackless_PCIConfig_Read ENDP\r
+\r
+;\r
+; ROM-based Global-Descriptor Table for the Tiano PEI Phase\r
+;\r
+align 16\r
+PUBLIC  BootGdtTable\r
+\r
+;\r
+; GDT[0]: 0x00: Null entry, never used.\r
+;\r
+NULL_SEL        equ     $ - GDT_BASE        ; Selector [0]\r
+GDT_BASE:\r
+BootGdtTable    DD      0\r
+                DD      0\r
+;\r
+; Linear data segment descriptor\r
+;\r
+LINEAR_SEL      equ     $ - GDT_BASE        ; Selector [0x8]\r
+        DW      0FFFFh                      ; limit 0xFFFF\r
+        DW      0                           ; base 0\r
+        DB      0\r
+        DB      092h                        ; present, ring 0, data, expand-up, writable\r
+        DB      0CFh                        ; page-granular, 32-bit\r
+        DB      0\r
+;\r
+; Linear code segment descriptor\r
+;\r
+LINEAR_CODE_SEL equ     $ - GDT_BASE        ; Selector [0x10]\r
+        DW      0FFFFh                      ; limit 0xFFFF\r
+        DW      0                           ; base 0\r
+        DB      0\r
+        DB      09Bh                        ; present, ring 0, data, expand-up, not-writable\r
+        DB      0CFh                        ; page-granular, 32-bit\r
+        DB      0\r
+;\r
+; System data segment descriptor\r
+;\r
+SYS_DATA_SEL    equ     $ - GDT_BASE        ; Selector [0x18]\r
+        DW      0FFFFh                      ; limit 0xFFFF\r
+        DW      0                           ; base 0\r
+        DB      0\r
+        DB      093h                        ; present, ring 0, data, expand-up, not-writable\r
+        DB      0CFh                        ; page-granular, 32-bit\r
+        DB      0\r
+\r
+;\r
+; System code segment descriptor\r
+;\r
+SYS_CODE_SEL    equ     $ - GDT_BASE        ; Selector [0x20]\r
+        DW      0FFFFh                      ; limit 0xFFFF\r
+        DW      0                           ; base 0\r
+        DB      0\r
+        DB      09Ah                        ; present, ring 0, data, expand-up, writable\r
+        DB      0CFh                        ; page-granular, 32-bit\r
+        DB      0\r
+;\r
+; Spare segment descriptor\r
+;\r
+SYS16_CODE_SEL  equ     $ - GDT_BASE        ; Selector [0x28]\r
+        DW      0FFFFh                      ; limit 0xFFFF\r
+        DW      0                           ; base 0\r
+        DB      0Fh\r
+        DB      09Bh                        ; present, ring 0, code, expand-up, writable\r
+        DB      00h                         ; byte-granular, 16-bit\r
+        DB      0\r
+;\r
+; Spare segment descriptor\r
+;\r
+SYS16_DATA_SEL  equ     $ - GDT_BASE        ; Selector [0x30]\r
+        DW      0FFFFh                      ; limit 0xFFFF\r
+        DW      0                           ; base 0\r
+        DB      0\r
+        DB      093h                        ; present, ring 0, data, expand-up, not-writable\r
+        DB      00h                         ; byte-granular, 16-bit\r
+        DB      0\r
+\r
+;\r
+; Spare segment descriptor\r
+;\r
+SPARE5_SEL      equ     $ - GDT_BASE        ; Selector [0x38]\r
+        DW      0                           ; limit 0xFFFF\r
+        DW      0                           ; base 0\r
+        DB      0\r
+        DB      0                           ; present, ring 0, data, expand-up, writable\r
+        DB      0                           ; page-granular, 32-bit\r
+        DB      0\r
+GDT_SIZE        EQU     $ - BootGDTtable    ; Size, in bytes\r
+\r
+;\r
+; GDT Descriptor\r
+;\r
+GdtDesc:                                    ; GDT descriptor\r
+        DW      GDT_SIZE - 1                ; GDT limit\r
+        DD      OFFSET BootGdtTable         ; GDT base address\r
+\r
+ProtectedModeEntryLinearAddress   LABEL   FWORD\r
+ProtectedModeEntryLinearOffset    LABEL   DWORD\r
+  DD      OFFSET ProtectedModeEntryPoint  ; Offset of our 32 bit code\r
+  DW      LINEAR_CODE_SEL\r
+\r
+END\r