1 ;------------------------------------------------------------------------------
3 ; Copyright (c) 2013-2015 Intel Corporation.
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
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.
19 ; This is the code that goes from real-mode to protected mode.
20 ; It consumes the reset vector, configures the stack.
23 ;------------------------------------------------------------------------------
27 ; Define assembler characteristics
33 ; Include processor definitions
40 ; CR0 cache control bit definition
42 CR0_CACHE_DISABLE EQU 040000000h
43 CR0_NO_WRITE EQU 020000000h
46 ; External and public declarations
47 ; TopOfStack is used by C code
48 ; SecStartup is the entry point to the C code
49 ; Neither of these names can be modified without
50 ; updating the C code.
52 EXTRN PlatformSecLibStartup: NEAR
53 EXTERNDEF C PcdGet32 (PcdEsramStage1Base):DWORD
56 ; Contrary to the name, this file contains 16 bit code as well.
58 _TEXT_REALMODE SEGMENT PARA PUBLIC USE16 'CODE'
59 ASSUME CS:_TEXT_REALMODE, DS:_TEXT_REALMODE
61 ;----------------------------------------------------------------------------
63 ; Procedure: _ModuleEntryPoint
69 ; Destroys: Assume all registers
73 ; Transition to non-paged flat-model protected mode from a
74 ; hard-coded GDT that provides exactly two descriptors.
75 ; This is a bare bones transition to protected mode only
76 ; used for a while in PEI and possibly DXE.
78 ; After enabling protected mode, a far jump is executed to
79 ; transfer to PEI using the newly loaded GDT.
83 ;----------------------------------------------------------------------------
85 _ModuleEntryPoint PROC C PUBLIC
88 ; Warm Reset (INIT#) check.
93 cmp BYTE PTR [si], 0EAh ; Is it warm reset ?
94 jne NotWarmReset ; JIf not.
105 ; Load the GDT table in GdtDesc
107 mov esi, OFFSET GdtDesc
109 lgdt fword ptr cs:[si]
112 ; Transition to 16 bit protected mode
114 mov eax, cr0 ; Get control register 0
115 or eax, 00000003h ; Set PE bit (bit #0) & MP bit (bit #1)
116 mov cr0, eax ; Activate protected mode
119 ; Now we're in 16 bit protected mode
120 ; Set up the selectors for 32 bit protected mode entry
130 ; Transition to Flat 32 bit protected mode
131 ; The jump to a far pointer causes the transition to 32 bit mode
133 mov esi, offset ProtectedModeEntryLinearAddress
134 jmp fword ptr cs:[si]
136 _ModuleEntryPoint ENDP
142 ; Protected mode portion initializes stack, configures cache, and calls C entry point
145 ;----------------------------------------------------------------------------
147 ; Procedure: ProtectedModeEntryPoint
149 ; Input: Executing in 32 Bit Protected (flat) mode
157 ; Output: This function never returns
166 ; Perform any essential early platform initilaisation
168 ; Call the main EDKII Sec C code
170 ;----------------------------------------------------------------------------
172 ProtectedModeEntryPoint PROC NEAR C PUBLIC
174 JMP32 stackless_EarlyPlatformInit
177 ; Set up stack pointer
179 mov esp, PcdGet32(PcdEsramStage1Base)
180 mov esi, QUARK_ESRAM_MEM_SIZE_BYTES
181 add esp, esi ; ESP = top of stack (stack grows downwards).
184 ; Store the the BIST value in EBP
186 mov ebp, 00h ; No processor BIST on Quark
189 ; Push processor count to stack first, then BIST status (AP then BSP)
196 jae PushProcessorCount
199 ; Some processors report 0 logical processors. Effectively 0 = 1.
200 ; So we fix up the processor count
208 ; We need to implement a long-term solution for BIST capture. For now, we just copy BSP BIST
209 ; for all processor threads
218 ; Pass Control into the PEI Core
220 call PlatformSecLibStartup
223 ; PEI Core should never return to here, this is just to capture an invalid return.
227 ProtectedModeEntryPoint ENDP
229 ;----------------------------------------------------------------------------
231 ; Procedure: stackless_EarlyPlatformInit
233 ; Input: esp - Return address
244 ; Any essential early platform initialisation required:
246 ; (2) Disable NMI's/SMI's
247 ; (3) Setup HMBOUND (defines what memory accesses go to MMIO/RAM)
248 ; (4) Setup eSRAM (provide early memory to the system)
249 ; (5) Setup PCIEXBAR access mechanism
250 ; (6) Open up full SPI flash decode
252 ;----------------------------------------------------------------------------
253 stackless_EarlyPlatformInit PROC NEAR C PUBLIC
256 ; Save return address
261 ; Ensure cache is disabled.
264 or eax, CR0_CACHE_DISABLE + CR0_NO_WRITE
270 ; Good convention suggests you should read back RTC data port after
271 ; accessing the RTC index port.
280 ; Disable SMI (Disables SMI wire, not SMI messages)
282 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)
283 JMP32 stackless_SideBand_Read
284 and eax, NOT (SMI_EN)
285 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)
286 JMP32 stackless_SideBand_Write
289 ; Before we get going, check SOC Unit Registers to see if we are required to issue a warm/cold reset
291 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)
292 JMP32 stackless_SideBand_Read
293 and eax, FORCE_WARM_RESET
294 jz TestForceColdReset ; Zero means bit clear, we're not requested to warm reset so continue as normal
298 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)
299 JMP32 stackless_SideBand_Read
300 and eax, FORCE_COLD_RESET
301 jz TestHmboundLock ; Zero means bit clear, we're not requested to cold reset so continue as normal
305 ; Before setting HMBOUND, check it's not locked
308 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)
309 JMP32 stackless_SideBand_Read
310 and eax, HMBOUND_LOCK
311 jz ConfigHmbound ; Zero means bit clear, we have the config we want so continue as normal
313 ; Failed to config - store sticky bit debug
315 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)
316 JMP32 stackless_SideBand_Read
317 or eax, RESET_FOR_HMBOUND_LOCK ; Set the bit we're interested in
318 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)
319 JMP32 stackless_SideBand_Write
323 ; Set up the HMBOUND register
326 mov eax, HMBOUND_ADDRESS ; Data (Set HMBOUND location)
327 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)
328 JMP32 stackless_SideBand_Write
331 ; Enable interrupts to Remote Management Unit when a IMR/SMM/HMBOUND violation occurs.
333 mov eax, ENABLE_IMR_INTERRUPT ; Data (Set interrupt enable mask)
334 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)
335 JMP32 stackless_SideBand_Write
340 mov eax, PcdGet32 (PcdEsramStage1Base) ; Data (Set eSRAM location)
341 shr eax, 18h ; Data (Set eSRAM location)
342 add eax, BLOCK_ENABLE_PG
343 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)
344 JMP32 stackless_SideBand_Write
346 ; Check that we're not blocked from setting the config that we want.
348 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)
349 JMP32 stackless_SideBand_Read
350 and eax, BLOCK_ENABLE_PG
351 jnz ConfigPci ; Non-zero means bit set, we have the config we want so continue as normal
353 ; Failed to config - store sticky bit debug
355 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)
356 JMP32 stackless_SideBand_Read
357 or eax, RESET_FOR_ESRAM_LOCK ; Set the bit we're interested in
358 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)
359 JMP32 stackless_SideBand_Write
366 mov eax, (EC_BASE + EC_ENABLE) ; Data
367 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)
368 JMP32 stackless_SideBand_Write
370 mov eax, (EC_BASE + EC_ENABLE) ; Data
371 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)
372 JMP32 stackless_SideBand_Write
375 ; Open up full 8MB SPI decode
377 mov ebx, PCI_CFG OR (ILB_PFA SHL 8) OR BDE ; PCI Configuration address
378 mov eax, DECODE_ALL_REGIONS_ENABLE
379 JMP32 stackless_PCIConfig_Write
382 ; Enable NMI operation
383 ; Good convention suggests you should read back RTC data port after
384 ; accessing the RTC index port.
393 ; Clear Host Bridge SMI, NMI, INTR fields
395 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)
396 JMP32 stackless_SideBand_Read
397 and eax, NOT(NMI + SMI + INTR) ; Clear NMI, SMI, INTR fields
398 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)
399 JMP32 stackless_SideBand_Write
402 ; Restore return address
409 ; Issue Warm Reset request to Remote Management Unit via iLB
411 mov ax, CF9_WARM_RESET
412 mov dx, ILB_RESET_REG
414 jmp $ ; Stay here until we are reset.
418 ; Issue Cold Reset request to Remote Management Unit via iLB
420 mov ax, CF9_COLD_RESET
421 mov dx, ILB_RESET_REG
423 jmp $ ; Stay here until we are reset.
425 stackless_EarlyPlatformInit ENDP
427 ;----------------------------------------------------------------------------
429 ; Procedure: stackless_SideBand_Read
431 ; Input: esp - return address
432 ; ecx[15:8] - Register offset
433 ; ecx[23:16] - Port ID
434 ; ecx[31:24] - Opcode
436 ; Output: eax - Data read
445 ; Perform requested sideband read
447 ;----------------------------------------------------------------------------
448 stackless_SideBand_Read PROC NEAR C PUBLIC
450 mov esi, esp ; Save the return address
453 ; Load the SideBand Packet Register to generate the transaction
455 mov ebx, PCI_CFG OR (HOST_BRIDGE_PFA SHL 8) OR MESSAGE_BUS_CONTROL_REG ; PCI Configuration address
456 mov cl, (ALL_BYTE_EN SHL SB_BE_FIELD) ; Set all Byte Enable bits
458 JMP32 stackless_PCIConfig_Write
462 ; Read the SideBand Data Register
464 mov ebx, PCI_CFG OR (HOST_BRIDGE_PFA SHL 8) OR MESSAGE_DATA_REG ; PCI Configuration address
465 JMP32 stackless_PCIConfig_Read
467 mov esp, esi ; Restore the return address
470 stackless_SideBand_Read ENDP
472 ;----------------------------------------------------------------------------
474 ; Procedure: stackless_SideBand_Write
476 ; Input: esp - return address
478 ; ecx[15:8] - Register offset
479 ; ecx[23:16] - Port ID
480 ; ecx[31:24] - Opcode
490 ; Perform requested sideband write
493 ;----------------------------------------------------------------------------
494 stackless_SideBand_Write PROC NEAR C PUBLIC
496 mov esi, esp ; Save the return address
499 ; Load the SideBand Data Register with the data
501 mov ebx, PCI_CFG OR (HOST_BRIDGE_PFA SHL 8) OR MESSAGE_DATA_REG ; PCI Configuration address
502 JMP32 stackless_PCIConfig_Write
505 ; Load the SideBand Packet Register to generate the transaction
507 mov ebx, PCI_CFG OR (HOST_BRIDGE_PFA SHL 8) OR MESSAGE_BUS_CONTROL_REG ; PCI Configuration address
508 mov cl, (ALL_BYTE_EN SHL SB_BE_FIELD) ; Set all Byte Enable bits
510 JMP32 stackless_PCIConfig_Write
513 mov esp, esi ; Restore the return address
516 stackless_SideBand_Write ENDP
518 ;----------------------------------------------------------------------------
520 ; Procedure: stackless_PCIConfig_Write
522 ; Input: esp - return address
523 ; eax - Data to write
524 ; ebx - PCI Config Address
532 ; Perform a DWORD PCI Configuration write
534 ;----------------------------------------------------------------------------
535 stackless_PCIConfig_Write PROC NEAR C PUBLIC
538 ; Write the PCI Config Address to the address port
541 mov dx, PCI_ADDRESS_PORT
546 ; Write the PCI DWORD Data to the data port
548 mov dx, PCI_DATA_PORT
553 stackless_PCIConfig_Write ENDP
555 ;----------------------------------------------------------------------------
557 ; Procedure: stackless_PCIConfig_Read
559 ; Input: esp - return address
560 ; ebx - PCI Config Address
562 ; Output: eax - Data read
569 ; Perform a DWORD PCI Configuration read
571 ;----------------------------------------------------------------------------
572 stackless_PCIConfig_Read PROC NEAR C PUBLIC
575 ; Write the PCI Config Address to the address port
578 mov dx, PCI_ADDRESS_PORT
583 ; Read the PCI DWORD Data from the data port
585 mov dx, PCI_DATA_PORT
590 stackless_PCIConfig_Read ENDP
593 ; ROM-based Global-Descriptor Table for the Tiano PEI Phase
599 ; GDT[0]: 0x00: Null entry, never used.
601 NULL_SEL equ $ - GDT_BASE ; Selector [0]
606 ; Linear data segment descriptor
608 LINEAR_SEL equ $ - GDT_BASE ; Selector [0x8]
609 DW 0FFFFh ; limit 0xFFFF
612 DB 092h ; present, ring 0, data, expand-up, writable
613 DB 0CFh ; page-granular, 32-bit
616 ; Linear code segment descriptor
618 LINEAR_CODE_SEL equ $ - GDT_BASE ; Selector [0x10]
619 DW 0FFFFh ; limit 0xFFFF
622 DB 09Bh ; present, ring 0, data, expand-up, not-writable
623 DB 0CFh ; page-granular, 32-bit
626 ; System data segment descriptor
628 SYS_DATA_SEL equ $ - GDT_BASE ; Selector [0x18]
629 DW 0FFFFh ; limit 0xFFFF
632 DB 093h ; present, ring 0, data, expand-up, not-writable
633 DB 0CFh ; page-granular, 32-bit
637 ; System code segment descriptor
639 SYS_CODE_SEL equ $ - GDT_BASE ; Selector [0x20]
640 DW 0FFFFh ; limit 0xFFFF
643 DB 09Ah ; present, ring 0, data, expand-up, writable
644 DB 0CFh ; page-granular, 32-bit
647 ; Spare segment descriptor
649 SYS16_CODE_SEL equ $ - GDT_BASE ; Selector [0x28]
650 DW 0FFFFh ; limit 0xFFFF
653 DB 09Bh ; present, ring 0, code, expand-up, writable
654 DB 00h ; byte-granular, 16-bit
657 ; Spare segment descriptor
659 SYS16_DATA_SEL equ $ - GDT_BASE ; Selector [0x30]
660 DW 0FFFFh ; limit 0xFFFF
663 DB 093h ; present, ring 0, data, expand-up, not-writable
664 DB 00h ; byte-granular, 16-bit
668 ; Spare segment descriptor
670 SPARE5_SEL equ $ - GDT_BASE ; Selector [0x38]
674 DB 0 ; present, ring 0, data, expand-up, writable
675 DB 0 ; page-granular, 32-bit
677 GDT_SIZE EQU $ - BootGDTtable ; Size, in bytes
682 GdtDesc: ; GDT descriptor
683 DW GDT_SIZE - 1 ; GDT limit
684 DD OFFSET BootGdtTable ; GDT base address
686 ProtectedModeEntryLinearAddress LABEL FWORD
687 ProtectedModeEntryLinearOffset LABEL DWORD
688 DD OFFSET ProtectedModeEntryPoint ; Offset of our 32 bit code