1 ;------------------------------------------------------------------------------
3 ; Copyright (c) 2013-2015 Intel Corporation.
5 ; SPDX-License-Identifier: BSD-2-Clause-Patent
13 ; This is the code that goes from real-mode to protected mode.
14 ; It consumes the reset vector, configures the stack.
17 ;------------------------------------------------------------------------------
21 ; Define assembler characteristics
27 ; Include processor definitions
34 ; CR0 cache control bit definition
36 CR0_CACHE_DISABLE EQU 040000000h
37 CR0_NO_WRITE EQU 020000000h
40 ; External and public declarations
41 ; TopOfStack is used by C code
42 ; SecStartup is the entry point to the C code
43 ; Neither of these names can be modified without
44 ; updating the C code.
46 EXTRN PlatformSecLibStartup: NEAR
47 EXTERNDEF C PcdGet32 (PcdEsramStage1Base):DWORD
50 ; Contrary to the name, this file contains 16 bit code as well.
52 _TEXT_REALMODE SEGMENT PARA PUBLIC USE16 'CODE'
53 ASSUME CS:_TEXT_REALMODE, DS:_TEXT_REALMODE
55 ;----------------------------------------------------------------------------
57 ; Procedure: _ModuleEntryPoint
63 ; Destroys: Assume all registers
67 ; Transition to non-paged flat-model protected mode from a
68 ; hard-coded GDT that provides exactly two descriptors.
69 ; This is a bare bones transition to protected mode only
70 ; used for a while in PEI and possibly DXE.
72 ; After enabling protected mode, a far jump is executed to
73 ; transfer to PEI using the newly loaded GDT.
77 ;----------------------------------------------------------------------------
79 _ModuleEntryPoint PROC C PUBLIC
82 ; Warm Reset (INIT#) check.
87 cmp BYTE PTR [si], 0EAh ; Is it warm reset ?
88 jne NotWarmReset ; JIf not.
99 ; Load the GDT table in GdtDesc
101 mov esi, OFFSET GdtDesc
103 lgdt fword ptr cs:[si]
106 ; Transition to 16 bit protected mode
108 mov eax, cr0 ; Get control register 0
109 or eax, 00000003h ; Set PE bit (bit #0) & MP bit (bit #1)
110 mov cr0, eax ; Activate protected mode
113 ; Now we're in 16 bit protected mode
114 ; Set up the selectors for 32 bit protected mode entry
124 ; Transition to Flat 32 bit protected mode
125 ; The jump to a far pointer causes the transition to 32 bit mode
127 mov esi, offset ProtectedModeEntryLinearAddress
128 jmp fword ptr cs:[si]
130 _ModuleEntryPoint ENDP
136 ; Protected mode portion initializes stack, configures cache, and calls C entry point
139 ;----------------------------------------------------------------------------
141 ; Procedure: ProtectedModeEntryPoint
143 ; Input: Executing in 32 Bit Protected (flat) mode
151 ; Output: This function never returns
160 ; Perform any essential early platform initilaisation
162 ; Call the main EDKII Sec C code
164 ;----------------------------------------------------------------------------
166 ProtectedModeEntryPoint PROC NEAR C PUBLIC
168 JMP32 stackless_EarlyPlatformInit
171 ; Set up stack pointer
173 mov esp, PcdGet32(PcdEsramStage1Base)
174 mov esi, QUARK_ESRAM_MEM_SIZE_BYTES
175 add esp, esi ; ESP = top of stack (stack grows downwards).
178 ; Store the the BIST value in EBP
180 mov ebp, 00h ; No processor BIST on Quark
183 ; Push processor count to stack first, then BIST status (AP then BSP)
190 jae PushProcessorCount
193 ; Some processors report 0 logical processors. Effectively 0 = 1.
194 ; So we fix up the processor count
202 ; We need to implement a long-term solution for BIST capture. For now, we just copy BSP BIST
203 ; for all processor threads
212 ; Pass Control into the PEI Core
214 call PlatformSecLibStartup
217 ; PEI Core should never return to here, this is just to capture an invalid return.
221 ProtectedModeEntryPoint ENDP
223 ;----------------------------------------------------------------------------
225 ; Procedure: stackless_EarlyPlatformInit
227 ; Input: esp - Return address
238 ; Any essential early platform initialisation required:
240 ; (2) Disable NMI's/SMI's
241 ; (3) Setup HMBOUND (defines what memory accesses go to MMIO/RAM)
242 ; (4) Setup eSRAM (provide early memory to the system)
243 ; (5) Setup PCIEXBAR access mechanism
244 ; (6) Open up full SPI flash decode
246 ;----------------------------------------------------------------------------
247 stackless_EarlyPlatformInit PROC NEAR C PUBLIC
250 ; Save return address
255 ; Ensure cache is disabled.
258 or eax, CR0_CACHE_DISABLE + CR0_NO_WRITE
264 ; Good convention suggests you should read back RTC data port after
265 ; accessing the RTC index port.
274 ; Disable SMI (Disables SMI wire, not SMI messages)
276 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)
277 JMP32 stackless_SideBand_Read
278 and eax, NOT (SMI_EN)
279 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)
280 JMP32 stackless_SideBand_Write
283 ; Before we get going, check SOC Unit Registers to see if we are required to issue a warm/cold reset
285 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)
286 JMP32 stackless_SideBand_Read
287 and eax, FORCE_WARM_RESET
288 jz TestForceColdReset ; Zero means bit clear, we're not requested to warm reset so continue as normal
292 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)
293 JMP32 stackless_SideBand_Read
294 and eax, FORCE_COLD_RESET
295 jz TestHmboundLock ; Zero means bit clear, we're not requested to cold reset so continue as normal
299 ; Before setting HMBOUND, check it's not locked
302 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)
303 JMP32 stackless_SideBand_Read
304 and eax, HMBOUND_LOCK
305 jz ConfigHmbound ; Zero means bit clear, we have the config we want so continue as normal
307 ; Failed to config - store sticky bit debug
309 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)
310 JMP32 stackless_SideBand_Read
311 or eax, RESET_FOR_HMBOUND_LOCK ; Set the bit we're interested in
312 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)
313 JMP32 stackless_SideBand_Write
317 ; Set up the HMBOUND register
320 mov eax, HMBOUND_ADDRESS ; Data (Set HMBOUND location)
321 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)
322 JMP32 stackless_SideBand_Write
325 ; Enable interrupts to Remote Management Unit when a IMR/SMM/HMBOUND violation occurs.
327 mov eax, ENABLE_IMR_INTERRUPT ; Data (Set interrupt enable mask)
328 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)
329 JMP32 stackless_SideBand_Write
334 mov eax, PcdGet32 (PcdEsramStage1Base) ; Data (Set eSRAM location)
335 shr eax, 18h ; Data (Set eSRAM location)
336 add eax, BLOCK_ENABLE_PG
337 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)
338 JMP32 stackless_SideBand_Write
340 ; Check that we're not blocked from setting the config that we want.
342 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)
343 JMP32 stackless_SideBand_Read
344 and eax, BLOCK_ENABLE_PG
345 jnz ConfigPci ; Non-zero means bit set, we have the config we want so continue as normal
347 ; Failed to config - store sticky bit debug
349 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)
350 JMP32 stackless_SideBand_Read
351 or eax, RESET_FOR_ESRAM_LOCK ; Set the bit we're interested in
352 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)
353 JMP32 stackless_SideBand_Write
360 mov eax, (EC_BASE + EC_ENABLE) ; Data
361 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)
362 JMP32 stackless_SideBand_Write
364 mov eax, (EC_BASE + EC_ENABLE) ; Data
365 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)
366 JMP32 stackless_SideBand_Write
369 ; Open up full 8MB SPI decode
371 mov ebx, PCI_CFG OR (ILB_PFA SHL 8) OR BDE ; PCI Configuration address
372 mov eax, DECODE_ALL_REGIONS_ENABLE
373 JMP32 stackless_PCIConfig_Write
376 ; Enable NMI operation
377 ; Good convention suggests you should read back RTC data port after
378 ; accessing the RTC index port.
387 ; Clear Host Bridge SMI, NMI, INTR fields
389 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)
390 JMP32 stackless_SideBand_Read
391 and eax, NOT(NMI + SMI + INTR) ; Clear NMI, SMI, INTR fields
392 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)
393 JMP32 stackless_SideBand_Write
396 ; Restore return address
403 ; Issue Warm Reset request to Remote Management Unit via iLB
405 mov ax, CF9_WARM_RESET
406 mov dx, ILB_RESET_REG
408 jmp $ ; Stay here until we are reset.
412 ; Issue Cold Reset request to Remote Management Unit via iLB
414 mov ax, CF9_COLD_RESET
415 mov dx, ILB_RESET_REG
417 jmp $ ; Stay here until we are reset.
419 stackless_EarlyPlatformInit ENDP
421 ;----------------------------------------------------------------------------
423 ; Procedure: stackless_SideBand_Read
425 ; Input: esp - return address
426 ; ecx[15:8] - Register offset
427 ; ecx[23:16] - Port ID
428 ; ecx[31:24] - Opcode
430 ; Output: eax - Data read
439 ; Perform requested sideband read
441 ;----------------------------------------------------------------------------
442 stackless_SideBand_Read PROC NEAR C PUBLIC
444 mov esi, esp ; Save the return address
447 ; Load the SideBand Packet Register to generate the transaction
449 mov ebx, PCI_CFG OR (HOST_BRIDGE_PFA SHL 8) OR MESSAGE_BUS_CONTROL_REG ; PCI Configuration address
450 mov cl, (ALL_BYTE_EN SHL SB_BE_FIELD) ; Set all Byte Enable bits
452 JMP32 stackless_PCIConfig_Write
456 ; Read the SideBand Data Register
458 mov ebx, PCI_CFG OR (HOST_BRIDGE_PFA SHL 8) OR MESSAGE_DATA_REG ; PCI Configuration address
459 JMP32 stackless_PCIConfig_Read
461 mov esp, esi ; Restore the return address
464 stackless_SideBand_Read ENDP
466 ;----------------------------------------------------------------------------
468 ; Procedure: stackless_SideBand_Write
470 ; Input: esp - return address
472 ; ecx[15:8] - Register offset
473 ; ecx[23:16] - Port ID
474 ; ecx[31:24] - Opcode
484 ; Perform requested sideband write
487 ;----------------------------------------------------------------------------
488 stackless_SideBand_Write PROC NEAR C PUBLIC
490 mov esi, esp ; Save the return address
493 ; Load the SideBand Data Register with the data
495 mov ebx, PCI_CFG OR (HOST_BRIDGE_PFA SHL 8) OR MESSAGE_DATA_REG ; PCI Configuration address
496 JMP32 stackless_PCIConfig_Write
499 ; Load the SideBand Packet Register to generate the transaction
501 mov ebx, PCI_CFG OR (HOST_BRIDGE_PFA SHL 8) OR MESSAGE_BUS_CONTROL_REG ; PCI Configuration address
502 mov cl, (ALL_BYTE_EN SHL SB_BE_FIELD) ; Set all Byte Enable bits
504 JMP32 stackless_PCIConfig_Write
507 mov esp, esi ; Restore the return address
510 stackless_SideBand_Write ENDP
512 ;----------------------------------------------------------------------------
514 ; Procedure: stackless_PCIConfig_Write
516 ; Input: esp - return address
517 ; eax - Data to write
518 ; ebx - PCI Config Address
526 ; Perform a DWORD PCI Configuration write
528 ;----------------------------------------------------------------------------
529 stackless_PCIConfig_Write PROC NEAR C PUBLIC
532 ; Write the PCI Config Address to the address port
535 mov dx, PCI_ADDRESS_PORT
540 ; Write the PCI DWORD Data to the data port
542 mov dx, PCI_DATA_PORT
547 stackless_PCIConfig_Write ENDP
549 ;----------------------------------------------------------------------------
551 ; Procedure: stackless_PCIConfig_Read
553 ; Input: esp - return address
554 ; ebx - PCI Config Address
556 ; Output: eax - Data read
563 ; Perform a DWORD PCI Configuration read
565 ;----------------------------------------------------------------------------
566 stackless_PCIConfig_Read PROC NEAR C PUBLIC
569 ; Write the PCI Config Address to the address port
572 mov dx, PCI_ADDRESS_PORT
577 ; Read the PCI DWORD Data from the data port
579 mov dx, PCI_DATA_PORT
584 stackless_PCIConfig_Read ENDP
587 ; ROM-based Global-Descriptor Table for the Tiano PEI Phase
593 ; GDT[0]: 0x00: Null entry, never used.
595 NULL_SEL equ $ - GDT_BASE ; Selector [0]
600 ; Linear data segment descriptor
602 LINEAR_SEL equ $ - GDT_BASE ; Selector [0x8]
603 DW 0FFFFh ; limit 0xFFFF
606 DB 092h ; present, ring 0, data, expand-up, writable
607 DB 0CFh ; page-granular, 32-bit
610 ; Linear code segment descriptor
612 LINEAR_CODE_SEL equ $ - GDT_BASE ; Selector [0x10]
613 DW 0FFFFh ; limit 0xFFFF
616 DB 09Bh ; present, ring 0, data, expand-up, not-writable
617 DB 0CFh ; page-granular, 32-bit
620 ; System data segment descriptor
622 SYS_DATA_SEL equ $ - GDT_BASE ; Selector [0x18]
623 DW 0FFFFh ; limit 0xFFFF
626 DB 093h ; present, ring 0, data, expand-up, not-writable
627 DB 0CFh ; page-granular, 32-bit
631 ; System code segment descriptor
633 SYS_CODE_SEL equ $ - GDT_BASE ; Selector [0x20]
634 DW 0FFFFh ; limit 0xFFFF
637 DB 09Ah ; present, ring 0, data, expand-up, writable
638 DB 0CFh ; page-granular, 32-bit
641 ; Spare segment descriptor
643 SYS16_CODE_SEL equ $ - GDT_BASE ; Selector [0x28]
644 DW 0FFFFh ; limit 0xFFFF
647 DB 09Bh ; present, ring 0, code, expand-up, writable
648 DB 00h ; byte-granular, 16-bit
651 ; Spare segment descriptor
653 SYS16_DATA_SEL equ $ - GDT_BASE ; Selector [0x30]
654 DW 0FFFFh ; limit 0xFFFF
657 DB 093h ; present, ring 0, data, expand-up, not-writable
658 DB 00h ; byte-granular, 16-bit
662 ; Spare segment descriptor
664 SPARE5_SEL equ $ - GDT_BASE ; Selector [0x38]
668 DB 0 ; present, ring 0, data, expand-up, writable
669 DB 0 ; page-granular, 32-bit
671 GDT_SIZE EQU $ - BootGDTtable ; Size, in bytes
676 GdtDesc: ; GDT descriptor
677 DW GDT_SIZE - 1 ; GDT limit
678 DD OFFSET BootGdtTable ; GDT base address
680 ProtectedModeEntryLinearAddress LABEL FWORD
681 ProtectedModeEntryLinearOffset LABEL DWORD
682 DD OFFSET ProtectedModeEntryPoint ; Offset of our 32 bit code