diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /ReferenceCode/Haswell/SampleCode/SecCore | |
download | zprj-master.tar.xz |
Diffstat (limited to 'ReferenceCode/Haswell/SampleCode/SecCore')
14 files changed, 3639 insertions, 0 deletions
diff --git a/ReferenceCode/Haswell/SampleCode/SecCore/CpuRcSec.cif b/ReferenceCode/Haswell/SampleCode/SecCore/CpuRcSec.cif new file mode 100644 index 0000000..0bc0424 --- /dev/null +++ b/ReferenceCode/Haswell/SampleCode/SecCore/CpuRcSec.cif @@ -0,0 +1,20 @@ +<component> + name = "CpuRcSec" + category = ModulePart + LocalRoot = "ReferenceCode\Haswell\SampleCode\SecCore" + RefName = "CpuRcSec" +[files] +"CpuRcSec.mak" +"CpuRcSec.sdl" +"Sec\Ia32\Chipset.inc" +"Sec\Ia32\CpuRcSec.asm" +"Sec\Ia32\CrcSecPpi.c" +"Sec\Ia32\Flat32.asm" +"Sec\Ia32\Ia32.inc" +"Sec\Ia32\SecFlat32.inc" +"Sec\Ia32\Platform.inc" +"Sec\Ia32\ResetVec.asm" +"Sec\Ia32\ResetVec.raw" +"Sec\Ia32\SecCore.inc" +"Sec\Ia32\SecStartup.c" +<endComponent> diff --git a/ReferenceCode/Haswell/SampleCode/SecCore/CpuRcSec.mak b/ReferenceCode/Haswell/SampleCode/SecCore/CpuRcSec.mak new file mode 100644 index 0000000..8f1b13f --- /dev/null +++ b/ReferenceCode/Haswell/SampleCode/SecCore/CpuRcSec.mak @@ -0,0 +1,27 @@ +# MAK file for the ModulePart:CPU SEC RC +CPU_RC_DEPENDANCIES = \ +$(CPU_RC_SEC_DIR)\Platform.inc \ +$(CPU_RC_SEC_DIR)\Chipset.inc \ +$(CPU_RC_SEC_DIR)\SecFlat32.inc + +$(BUILD_DIR)\CpuRcSec.obj : $(CPU_RC_SEC_DIR)\CpuRcSec.asm $(CPU_RC_DEPENDANCIES) + $(ASM) /c /nologo /coff /Sa /I$(BUILD_DIR) /Fo$@ $(CPU_RC_SEC_DIR)\CpuRcSec.asm + + +# Add its own include path to +MY_INC = \ +/ICore \ +/IEDK\Foundation\Framework\Ppi\SecPlatformInformation + +# Add CrcSecPpi.obj to CORE_PEIBin dependency list, so it will be linked with PEI CORE +CORE_PEIBin: $(BUILD_DIR)\CrcSecPpi.obj +# Add SecPlatformInformation.obj to CORE_PEIBin dependency list, so it will be linked with PEI CORE +CORE_PEIBin: $(BUILD_DIR)\SecPlatformInformation.obj + +# Add a description block for CrcSecPpi.OBJ for cross-module link +$(BUILD_DIR)\CrcSecPpi.OBJ : $(CPU_RC_SEC_DIR)\CrcSecPpi.c + $(CC) $(CFLAGS) $(MY_INC) /Fo$(BUILD_DIR)\CrcSecPpi.obj $(CPU_RC_SEC_DIR)\CrcSecPpi.c + +# Add a description block for SecPlatformInformation.OBJ +$(BUILD_DIR)\SecPlatformInformation.obj : $(EdkFrameworkPpiLib_DIR)\SECPLATFORMINFORMATION\SecPlatformInformation.c + $(CC) $(CFLAGS) $(EDK_INCLUDES) /D TIANO_RELEASE_VERSION=0x00080006 /Fo$(BUILD_DIR)\SecPlatformInformation.obj $(EdkFrameworkPpiLib_DIR)\SECPLATFORMINFORMATION\SecPlatformInformation.c diff --git a/ReferenceCode/Haswell/SampleCode/SecCore/CpuRcSec.sdl b/ReferenceCode/Haswell/SampleCode/SecCore/CpuRcSec.sdl new file mode 100644 index 0000000..3c8a5b0 --- /dev/null +++ b/ReferenceCode/Haswell/SampleCode/SecCore/CpuRcSec.sdl @@ -0,0 +1,40 @@ +TOKEN + Name = "Intel_Haswell_SEC_RC_SUPPORT" + Value = "1" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + TargetH = Yes + Master = Yes +End + +MODULE + Help = "Includes CpuRcSec.mak to Project" + File = "CpuRcSec.mak" +End + +ELINK + Name = "$(BUILD_DIR)\CpuRcSec.obj" + Parent = "ADDON_SEC_CORE_OBJ_FILES" + InvokeOrder = AfterParent +End + +PATH + Name = "CPU_RC_SEC_DIR" + Path = "ReferenceCode\Haswell\SampleCode\SecCore\Sec\Ia32" +End + +ELINK + Name = "GainestownSecRcEntry" + Parent = "SECCoreAtPowerOn" + Priority = 1000 + Help = "Gainestown RC" + InvokeOrder = AfterParent +End + +ELINK + Name = "CrcSecPlatformInformationPpi," + Parent = "PeiCoreInitialize" + InvokeOrder = AfterParent +End + diff --git a/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/Chipset.inc b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/Chipset.inc new file mode 100644 index 0000000..ebd52ab --- /dev/null +++ b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/Chipset.inc @@ -0,0 +1,107 @@ +;@file +; Chipset constants and macros +; +;@copyright +; Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved +; This software and associated documentation (if any) is furnished +; under a license and may only be used or copied in accordance +; with the terms of the license. Except as permitted by such +; license, no part of this software or documentation may be +; reproduced, stored in a retrieval system, or transmitted in any +; form or by any means without the express written consent of +; Intel Corporation. +; +; This file contains a 'Sample Driver' and is licensed as such +; under the terms of your license agreement with Intel or your +; vendor. This file may be modified by the user, subject to +; the additional terms of the license agreement +; + +; +; APIC register +; +APICID EQU 0FEE00020h + +; +; Power Management I/O Registers +; +PCH_ACPI_BASE_ADDRESS EQU 0500h +ACPI_PM1_STS EQU 000h +ACPI_PM1_CNT EQU 004h + +; +; PCH RCBA base address +; +PCH_RCRB_BASE EQU 0FED1C000h +PCH_RCRB_BASE_REG EQU 8000F8F0h ; PCH Register B0:D31:RF0 +PCH_RCRB_GCS EQU 03410h +PCH_RCRB_RTC_CONF EQU 03400h +PCH_RCRB_RTC_CONF_UCMOS_EN EQU 04h +PCH_RCRB_HPET EQU 03404h +PCH_RCRB_HPET_DECODE EQU 080h + +; +; HPET compare register +; +HPET_COMP_1 EQU 0FED00108h +HPET_COMP_2 EQU 0FED0010Ch +HPET_COMP_3 EQU 0FED00128h +HPET_COMP_4 EQU 0FED00148h + +; +; MCH PCIe base address +; +;Need to match PcdPciExpressBaseAddress or PCIEX_BASE_ADDRESS +;CPU_HEC_BASE EQU 0E0000000h ; Must be X0000000 +;(AMI_CHG)> +CPU_HEC_BASE EQU MKF_PCIEX_BASE_ADDRESS ; Must be X0000000 +;<(AMI_CHG) +;CPU_HEC_SIZE EQU 000000000h ; 256M +;(AMI_CHG)> +CPU_HEC_SIZE EQU MKF_PCIEX_LENGTH_BIT_SETTING ; 64M, 128M, 256M +;<(AMI_CHG) +CPU_HEC_EN EQU 000000001h ; Enable +CPU0_HEC_PCI_ADDR EQU 080FF0150h +CPU1_HEC_PCI_ADDR EQU 080FE0150h + +PCI_LPC_BASE EQU 08000F800h + +GPIO_BASE_ADDRESS EQU 0800h +R_GPIO_USE_SEL2 EQU 030h +R_GPIO_IO_SEL2 EQU 034h +R_GPIO_LVL2 EQU 038h + +; +; PCI registers +; +PCH_LPC_PMBASE_PCI_ADDR EQU ((1Fh * 8 + 00h) * 1000h + 0040h + CPU_HEC_BASE) +PCH_LPC_ACPICNTL_PCI_ADDR EQU ((1Fh * 8 + 00h) * 1000h + 0044h + CPU_HEC_BASE) +PCH_LPC_GEN_PMCON_3_ADDR EQU ((1Fh * 8 + 00h) * 1000h + 00A4h + CPU_HEC_BASE) +PCH_LPC_RCRB_PCI_ADDR EQU ((1Fh * 8 + 00h) * 1000h + 00F0h + CPU_HEC_BASE) +PCH_LPC_BIOS_CNTL_PCI_ADDR EQU ((1Fh * 8 + 00h) * 1000h + 00DCh + CPU_HEC_BASE) +MCH_UNCERRMASK_PCI_ADDR EQU ((00h * 8 + 00h) * 1000h + 0108h + CPU_HEC_BASE) +MCH_SYRE_PCI_ADDR EQU ((10h * 8 + 00h) * 1000h + 0040h + CPU_HEC_BASE) + +SYRE_CPURST EQU 14 + +; +; PCIEXBAR constants for enable in bit [0] +; +ENABLE EQU 1 + +; +; PCIEXBAR constants for size in bit [2:1] +; +PCIEXBAR_64MB EQU 010b +PCIEXBAR_128MB EQU 001b +PCIEXBAR_256MB EQU 000b + +MMCFG_BASE EQU CPU_HEC_BASE ; 4GB-128MB +MMCFG_LENGTH_BIT_SETTING EQU CPU_HEC_SIZE ; 64M, 128M, 256M + +DMIBAR_REG EQU (068h + CPU_HEC_BASE) +DMI_BASE_ADDRESS EQU 0FED18000h + +MCHBAR_REG EQU (048h + CPU_HEC_BASE) +MCH_BASE_ADDRESS EQU 0FED10000h + diff --git a/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/CpuRcSec.asm b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/CpuRcSec.asm new file mode 100644 index 0000000..1460ddf --- /dev/null +++ b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/CpuRcSec.asm @@ -0,0 +1,38 @@ + + INCLUDE Token.equ + INCLUDE Platform.inc + INCLUDE Ia32.inc + +CPU_HEC_BASE EQU MKF_PCIEX_BASE_ADDRESS ; Must defined before include Chipset.inc + INCLUDE Chipset.inc + + INCLUDE SecCore.inc + + .686p + .xmm + .model small + + extern FindMicrocode:NEAR32 + extern GainestownSecRcEntryEnd:NEAR32 + +STARTUP_SEG SEGMENT PARA PUBLIC USE32 'CODE' + ASSUME CS:STARTUP_SEG, DS:STARTUP_SEG + + INCLUDE SecFlat32.inc + +GainestownSecRcEntry PROC + + jmp ProtectedModeSECStart ; Jump to IvyBridge SEC sample code + +CallPeiCoreEntryPoint PROC + ; Set stack top pointer + mov esp, DATA_STACK_BASE_ADDRESS + DATA_STACK_SIZE + + jmp GainestownSecRcEntryEnd ; Exit the eLink +CallPeiCoreEntryPoint ENDP + +GainestownSecRcEntry ENDP + +STARTUP_SEG ENDS +END + diff --git a/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/CrcSecPpi.c b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/CrcSecPpi.c new file mode 100644 index 0000000..28cc105 --- /dev/null +++ b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/CrcSecPpi.c @@ -0,0 +1,233 @@ +/*++ + This file contains an 'Intel Peripheral Driver' and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement +--*/ +/*++ + +Copyright (c) 1999 - 2008 Intel Corporation. All rights reserved +This software and associated documentation (if any) is furnished +under a license and may only be used or copied in accordance +with the terms of the license. Except as permitted by such +license, no part of this software or documentation may be +reproduced, stored in a retrieval system, or transmitted in any +form or by any means without the express written consent of +Intel Corporation. + + +Module Name: + + CrcSecPpi.c + +Abstract: + + Install SecPlatformInformation PPI. + +--*/ + +//#include "Tiano.h" +//#include "PeiCore.h" +//#include "FlashMap.h" +//#include "EfiFirmwareFileSystem.h" +//#include "EfiFirmwareVolumeHeader.h" + +//#include EFI_PPI_DEFINITION (SecPlatformInformation) +#include "Tiano.h" +//#include <Core\Core_Pei\PeiCore.h> + +//#include "Efi.h" +//#include "Pei.h" + +#include "EfiCommonLib.h" +#include <Ppi\AmiEarlyBistPpi.h> +static EFI_GUID gAmiEarlyBistGuid = AMI_EARLY_BIST_PPI_GUID; + +#include "SecPlatformInformation.h" + +EFI_STATUS +SecPlatformInformation ( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT UINT64 *StructureSize, + IN OUT SEC_PLATFORM_INFORMATION_RECORD *PlatformInformationRecord + ); + +EFI_SEC_PLATFORM_INFORMATION_PPI mSecPlatformInformationPpi = { SecPlatformInformation }; + +EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformationPpi = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiSecPlatformInformationPpiGuid, + &mSecPlatformInformationPpi +}; + +EFI_STATUS +EFIAPI +SecPlatformInformation ( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT UINT64 *StructureSize, + IN OUT SEC_PLATFORM_INFORMATION_RECORD *PlatformInformationRecord + ) +/*++ + +Routine Description: + + Implementation of the PlatformInformation service in + EFI_SEC_PLATFORM_INFORMATION_PPI. + This function conveys state information out of the SEC phase into PEI. + +Arguments: + + PeiServices - Pointer to the PEI Services Table. + StructureSize - Pointer to the variable describing size of the input buffer. + PlatformInformationRecord - Pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD. + +Returns: + + EFI_SUCCESS - The data was successfully returned. + EFI_BUFFER_TOO_SMALL - The buffer was too small. + +--*/ +{ + UINT32 *BIST; + UINT32 Size; + UINT32 Count; + AMI_EARLY_BIST_PPI *AmiEarlyPpi; + EFI_STATUS Status; + CPU_BIST PrivateBist; + + Status = (*PeiServices)->LocatePpi( + PeiServices, + &gAmiEarlyBistGuid, + 0, NULL, + &AmiEarlyPpi + ); + //Force BIST no error if PPI not found + if (Status != EFI_SUCCESS) { + Size = sizeof (UINT64); + if ((*StructureSize) < (UINT64) Size) { + *StructureSize = Size; + return EFI_BUFFER_TOO_SMALL; + } + PrivateBist.ApicId = 0; + PrivateBist.Bist = 0; + BIST = (UINT32*)&PrivateBist; + } else{ + Count = AmiEarlyPpi->NumBists; + Size = Count * sizeof (UINT64); + if ((*StructureSize) < (UINT64) Size) { + *StructureSize = Size; + return EFI_BUFFER_TOO_SMALL; + } + BIST = (UINT32 *) (&(AmiEarlyPpi->CpuBist)); + } + *StructureSize = Size; + EfiCommonLibCopyMem (PlatformInformationRecord, BIST, Size); + + return EFI_SUCCESS; + +/* + UINT32 *BIST; + UINT32 Size; + UINT32 Count; + + // + // The entries of BIST information, together with the number of them, + // reside in the bottom of stack, left untouched by normal stack operation. + // This routine copies the BIST information to the buffer pointed by + // PlatformInformationRecord for output. + // + Count = *(TopOfCar - 1); + Size = Count * sizeof (UINT64); + + if ((*StructureSize) < (UINT64) Size) { + *StructureSize = Size; + return EFI_BUFFER_TOO_SMALL; + } + + *StructureSize = Size; + BIST = (UINT32 *) ((UINT32) TopOfCar - sizeof (UINT32) - Size); + + EfiCommonLibCopyMem (PlatformInformationRecord, BIST, Size); + + return EFI_SUCCESS; +*/ +} + +//<AMI_PHDR_START> +//********************************************************************** +// +// Procedure: CrcSecPlatformInformationPpi +// +// Description: +// Install SecPlatformInformation PPI that Intel Ivybridge CPU reference code needs. +// (conveys state information out of the SEC phase into PEI) +// +// Input: +// IN EFI_FFS_FILE_HEADER *FfsHeader - pointer to the header of the current firmware file system +// IN EFI_PEI_SERVICES **PeiServices - pointer to the PeiServices Table +// +// Output: +// EFI_SUCCESS +// +// Notes: +// +//********************************************************************** +//<AMI_PHDR_END> +//PeiInitialize eLink + +EFI_STATUS EFIAPI CrcSecPlatformInformationPpi( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices +){ + EFI_STATUS Status; + + // Install the NB Init Policy PPI + Status = (*PeiServices)->InstallPpi(PeiServices, &mPeiSecPlatformInformationPpi); + + return EFI_SUCCESS; +} + + +// VOID +// SecStartup ( +// IN UINT32 SizeOfRam, +// IN UINT32 BootFirmwareVolume, +// IN PEI_MAIN_ENTRY_POINT PeiCoreEntryPoint +// ) +/*++ + +Routine Description: + + Entry point to the C language phase of SEC. After the SEC assembly + code has initialized some temporary memory and set up the stack, + the control is transferred to this function. + +Arguments: + + SizeOfRam - Size of the temporary memory available for use. + BootFirmwareVolume - Base address of the Boot Firmware Volume. + PeiCoreEntryPoint - Pointer to the entry point of the PEI core. + +Returns: + + This function never returns + +--*/ +// { +// EFI_PEI_STARTUP_DESCRIPTOR PeiStartup; +// +// PeiStartup.SizeOfCacheAsRam = SizeOfRam; +// PeiStartup.BootFirmwareVolume = BootFirmwareVolume; +// PeiStartup.DispatchTable = &mPeiSecPlatformInformationPpi; +// +// // +// // Transfer the control to the PEI core +// // +// (*PeiCoreEntryPoint) (&PeiStartup); +// +// // +// // Should not come here. +// // +// return ; +// } diff --git a/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/Flat32.asm b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/Flat32.asm new file mode 100644 index 0000000..3b973d8 --- /dev/null +++ b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/Flat32.asm @@ -0,0 +1,1490 @@ +; +; This file contains a 'Sample Driver' and is licensed as such +; under the terms of your license agreement with Intel or your +; vendor. This file may be modified by the user, subject to +; the additional terms of the license agreement +; +;------------------------------------------------------------------------------ +; +; Copyright (c) 1999 - 2013, Intel Corporation. All rights reserved.<BR> +; This software and associated documentation (if any) is furnished +; under a license and may only be used or copied in accordance +; with the terms of the license. Except as permitted by such +; license, no part of this software or documentation may be +; reproduced, stored in a retrieval system, or transmitted in any +; form or by any means without the express written consent of +; Intel Corporation. +; +; Module Name: +; +; Flat32.asm +; +; Abstract: +; +; This is the code that goes from real-mode to protected mode. +; It consumes the reset vector. +; +;------------------------------------------------------------------------------ + INCLUDE Platform.inc + INCLUDE Ia32.inc + INCLUDE Chipset.inc + INCLUDE SecCore.inc + +.686p +.xmm +.model small, c + +EXTRN SecStartup:NEAR + +; ECP porting +EXTRN PcdGet32 (PcdFlashMicrocodeFvBase):DWORD +EXTRN PcdGet32 (PcdFlashMicrocodeFvSize):DWORD +EXTRN PcdGet32 (PcdNemCodeCacheSize):DWORD +EXTRN PcdGet32 (PcdNemCodeCacheBase):DWORD +EXTRN PcdGet32 (PcdFlashAreaBaseAddress):DWORD +EXTRN PcdGet32 (PcdTemporaryRamBase):DWORD +EXTRN PcdGet32 (PcdTemporaryRamSize):DWORD +EXTRN PcdGet64 (PcdPciExpressBaseAddress):QWORD + +_TEXT_REALMODE SEGMENT PARA PUBLIC USE16 'CODE' + ASSUME CS:_TEXT_REALMODE, DS:_TEXT_REALMODE + +;------------------------------------------------------------------------------ +; +; SEC "Security" Code module. +; +; Transition to non-paged flat-model protected mode from a +; hard-coded GDT that provides exactly two descriptors. +; This is a bare bones transition to protected mode only +; used for while in PEI and possibly DXE. +; +; IA32 specific cache as RAM modules +; +; After enabling protected mode, a far jump is executed to +; TransferToPEI using the newly loaded GDT. +; This code also enables the Cache-as-RAM +; +; RETURNS: none +; +; MMX Usage: +; MM0 = BIST State +; MM1 = Current Package Physical Info +; [7:0] = Cluster ID +; [15:8] = Total Prossor pacakge detected in system +; [16] = BAD CMOS Flag +; [17] = AuburnDale or ClarksField +; [0] = AuburnDale +; [1] = ClarksField +; [18] = Contain SEC reset flag +; CPU Only Reset Flag +; [19] = Contain SEC reset flag +; Power Good Reset Flag +; [23:20] = Reserved +; [31:24] = Reserved +; MM2 = store common MAX & MIN ratio +; MM3 = Patch Revision +; MM4 = Patch Pointer +; MM5 = Save time-stamp counter value high32bit +; MM6 = Save time-stamp counter value low32bit. +; MM7 = Used in CALL_MMX & RET_ESI micaro +; +;------------------------------------------------------------------------------ + +; Nehalem Reset Boot Flow Start + +align 4 +_ModuleEntryPoint PROC NEAR C PUBLIC + ; + ; Save BIST state in MM0 + ; + fninit ; clear any pending Floating point exceptions + movd mm0, eax + + ; + ; Save time-stamp counter value + ; rdtsc load 64bit time-stamp counter to EDX:EAX + ; + rdtsc + movd mm5, edx + movd mm6, eax +;---------------------------------------------------------------------------------------- +; "Merlin" support +;---------------------------------------------------------------------------------------- + xor eax, eax + mov es, ax + mov ax, cs + mov ds, ax + +;****************************************************************************** +; BEGIN WARM-START CHANGE +;****************************************************************************** +; +; PLATFORM-SPECIFIC EQUATES! +; These equates define an address which has the following requirements +; on the target platform: +; 1. After booting DOS, the memory is not used by other DOS applications +; or drivers (thus very platform/configuration specific). +; Minimum of roughly 8 bytes required. +; 2. The memory contents and address range are not affected by an INIT +; 3. By default, after booting DOS, the first 4 bytes at this address +; contain either 0 (cleared memory) or 0xFFFFFFFF. +; 4. After booting DOS, the memory is writable +; +; It's expected that a manual inspection (using ITP) is performed to ensure +; that the requirements are met. If the manual inspection fails, then a +; different address must be identified, the below two equates must be +; changed accordingly, and the platform firmware must be rebuilt. +; Note that simply changing the platform hardware configuration could +; break this firmware because drivers may be loaded differently in +; memory, potentially using the address arbitrarily chosen here. +; + ; + ; Check if value in magic address contains non-zero/non-FF value. + ; It should actually contain executable code, typically a jmp + ; instruction. + ; + mov ax, MAGIC_SEG + mov es, ax + mov al, BYTE PTR es:[MAGIC_ADDRESS_IN_SEG] + + ; Check for zero value + cmp al, 0EAh ; EA is the FAR JMP opcode that Merlin inserts + jz LegacyBiosWarmStart + + ; Check INIT# is asserted by port 0xCF9 + mov dx, 0CF9h + in al, dx + cmp al, 04h + jnz NotWarmStart + + ; + ; Issue hard reset due to client silicon limitations, CPU Only Reset is not supported. + ; + mov dx, 0CF9h + mov al, 06h + out dx, al + +LegacyBiosWarmStart: + + ; + ; Check APIC_BASE_MSR.BIT8 to see if we're the BSP + ; + mov cx, MSR_APIC_BASE + rdmsr + test ah, 1 + jz TightLoop + ; + ; We're the BSP, so jump to the magic address. + ; + DB 0EAh + DW MAGIC_ADDRESS_IN_SEG + DW MAGIC_SEG + + ; Not reached +NotWarmStart: + +;****************************************************************************** +; END WARM-START CHANGE +;****************************************************************************** + + ; + ; Enter Protected mode. + ; + STATUS_CODE (01h) ; BSP_PROTECTED_MODE_START + mov esi, OFFSET GdtDesc + DB 66h + lgdt fword ptr cs:[si] + mov eax, cr0 ; Get control register 0 + or eax, 00000003h ; Set PE bit (bit #0) & MP bit (bit #1) + mov cr0, eax ; Activate protected mode + mov eax, cr4 ; Get control register 4 + or eax, 00000600h ; Set OSFXSR bit (bit #9) & OSXMMEXCPT bit (bit #10) + mov cr4, eax + + ; + ; Now we're in Protected16 + ; Set up the selectors for protected mode entry + ; + mov ax, SYS_DATA_SEL + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + + ; + ; Go to Protected32 + ; + mov esi, offset NemInitLinearAddress + jmp fword ptr cs:[si] + +TightLoop: + cli + hlt + jmp TightLoop + +_ModuleEntryPoint ENDP +_TEXT_REALMODE ENDS + +_TEXT_PROTECTED_MODE SEGMENT PARA PUBLIC USE32 'CODE' + ASSUME CS:_TEXT_PROTECTED_MODE, DS:_TEXT_PROTECTED_MODE + +CALL_MMX macro RoutineLabel + + local ReturnAddress + mov esi, offset ReturnAddress + movd mm7, esi ; save ReturnAddress into MM7 + jmp RoutineLabel +ReturnAddress: + +endm + +RET_ESI macro + + movd esi, mm7 ; restore ESP from MM7 + jmp esi + +endm + +CALL_EBP macro RoutineLabel + + local ReturnAddress + mov ebp, offset ReturnAddress + jmp RoutineLabel +ReturnAddress: + +endm + +RET_EBP macro + + jmp ebp ; restore ESP from EBP + +endm + +align 4 +ProtectedModeSECStart PROC NEAR PUBLIC + + STATUS_CODE (02h) + CALL_MMX EnableAccessCSR + + STATUS_CODE (03h) + CALL_EBP VeryEarlyMicrocodeUpdate + + STATUS_CODE (04h) + CALL_MMX DetectNumOfCPUSocket + + STATUS_CODE (05h) + CALL_MMX PlatformInitialization + + STATUS_CODE (06h) + CALL_MMX InitializeNEM + + STATUS_CODE (07h) + CALL_MMX EstablishStack + + STATUS_CODE (08h) + jmp CallPeiCoreEntryPoint + +ProtectedModeSECStart ENDP + +EnableAccessCSR PROC NEAR PRIVATE + ; + ; get Bus number from CPUID[1] EBX[31:24] + ; + + mov eax, 0Bh + mov ecx, 1 + cpuid + mov esi, eax + + mov eax, 1 ; bus 0 + cpuid + bswap ebx + movzx eax, bl + movzx ebx, bl + shl eax, BSPApicIDSaveStart ; Save current BSP APIC ID in MM1[31:24] + mov cx, si + shr bl, cl ; get Bus number in BL + or eax, ebx + movd mm1, eax ; save Bus number MM1[7:0] + + ; + ; Enable MM PCI-E Config Space + ; --cr-- use register symbol name; should upper 32 bit be cleared + ; + mov eax, 080000060h ; MCHBAR + mov dx, 0CF8h + out dx, eax + mov dx, 0CFCh + mov eax, 04h + out dx, eax + in eax, dx + or eax, MMCFG_BASE OR ENABLE + out dx, eax + + ; Clear reset flag + movd eax, mm1 + and eax, NOT BIT18+BIT19 + movd mm1, eax + + ; + ; Enable SPI prefetching and caching + ; + mov esi, PCH_LPC_BIOS_CNTL_PCI_ADDR ; Bus0:Dev31:Func0:RegDCh + and BYTE PTR es:[esi], NOT (11b SHL 2) + or BYTE PTR es:[esi], (10b SHL 2) ; D31:F0:RegDCh[3:2] = 10b + + RET_ESI + +EnableAccessCSR ENDP + +; STATUS_CODE (03h) +PlatformInitialization PROC NEAR PRIVATE + + ; + ; Program PCI Express base address + ; + + mov eax, 80000060h ; 0:0:0:60 + mov dx, 0CF8h + out dx, eax + mov dx, 0CFCh + ;using Pcd instead + ;mov eax, 0e0000000h OR 00h OR 1 +; mov eax, DWORD PTR PcdGet64 (PcdPciExpressBaseAddress) + mov eax, DWORD PTR PCIEXPRESS_BASE_ADDRESS + or eax, (PCIEX_LENGTH_BIT_SETTING OR 1) + out dx, eax + + ; + ; Enable Mch Bar + ; + mov esi, MCHBAR_REG + mov eax, (MCH_BASE_ADDRESS + 1) + mov Dword Ptr [esi], eax + + ; + ; Enable RCRB in PCH. + ; + mov esi, PCH_LPC_RCRB_PCI_ADDR + mov eax, PCH_RCRB_BASE + 1 + mov Dword Ptr [esi], eax + + ; + ; Configure GPIO to be able to initiate LVL change for GPIO48 for S3 resume time calculation. + ; + ; Enable GPIO BASE I/O registers + ; + mov eax, PCI_LPC_BASE + 48h + mov dx, 0CF8h + out dx, eax + mov eax, GPIO_BASE_ADDRESS + add dx, 4 + out dx, eax + + mov eax, PCI_LPC_BASE + 4Ch + mov dx, 0CF8h + out dx, eax + add dx, 4 + in al, dx + or al, BIT4 ; GPIOBASE Enable + out dx, al + + ;GPIO_USE_SEL2 Register -> 1 = GPIO 0 = Native + mov dx, GPIO_BASE_ADDRESS + R_GPIO_USE_SEL2 + in eax, dx + or eax, 010000h ;Enable GPIO48 + out dx, eax + + ;GP_IO_SEL2 Register -> 1 = Input 0 = Output (if Native Mode don't care) + mov dx, GPIO_BASE_ADDRESS + R_GPIO_IO_SEL2 + in eax, dx + and eax, 0FFFEFFFFh ;Configure GPIO48 as Output + out dx, eax + + mov dx, GPIO_BASE_ADDRESS + R_GPIO_LVL2 + in eax, dx + or eax, 010000h ;Configure GPIO48 as High + out dx, eax + + ; + ; Program and Enable ACPI PM Base. + ; + mov esi, PCH_LPC_PMBASE_PCI_ADDR + mov eax, PCH_ACPI_BASE_ADDRESS + 1 + mov Dword Ptr [esi], eax + mov esi, PCH_LPC_ACPICNTL_PCI_ADDR + or Dword Ptr [esi], 00000080h + + ; + ; PCH BIOS Spec Rev 0.5.0 Section 12.9 + ; Additional Programming Requirements for USB Support + ; Step 2.b + ; Clear RCBA + 3598h [0] to 0b + ; + mov esi, PCH_RCRB_BASE + 3598h + mov eax, 0 + mov Dword Ptr [esi], eax + + ; + ; Enable HPET decode in PCH. + ; + mov esi, PCH_RCRB_BASE + PCH_RCRB_HPET + mov eax, PCH_RCRB_HPET_DECODE + mov Dword Ptr [esi], eax + mov eax, Dword ptr [esi] + xor eax, eax + mov esi, HPET_COMP_1 + mov Dword Ptr [esi], eax + mov esi, HPET_COMP_2 + mov Dword ptr [esi], eax + + ; + ; Enable the upper 128-byte bank of RTC RAM. + ; + mov esi, PCH_RCRB_BASE + PCH_RCRB_RTC_CONF + mov eax, Dword Ptr [esi] + or eax, PCH_RCRB_RTC_CONF_UCMOS_EN + mov Dword Ptr [esi], eax + + ; + ; Choose Port80 Route + ; + mov esi, PCH_RCRB_BASE + PCH_RCRB_GCS + mov ebx, Dword Ptr [esi] + or bl, BIT5 + + ; + ; check SETUP option - PchPort80Route + ; 0 = LPC {Default]; 1 = PCI + ; +; mov al, CMOS_PCH_PORT80_OFFSET ; CMOS Offset = 17h +; mov dx, RTC_UPPER_INDEX +; out dx, al +; inc dx +; in al, dx +; test al, BIT0 +; jnz @F + and bl, NOT (BIT2) ; Port80h to LPC +;@@: + mov Dword Ptr [esi], ebx + + ; + ; Halt TCO Timer + ; + mov dx, 0468h + in ax, dx + or ax, BIT11 + out dx, ax + + ; + ; Clear the Second TO status bit + ; + mov dx, 0466h + in ax, dx + or ax, BIT1 + out dx, ax + + RET_ESI + +PlatformInitialization ENDP + +; STATUS_CODE (03h) +DetectNumOfCPUSocket PROC NEAR PRIVATE + + ; only one socket + movd eax, mm1 ; get MM1 value into EAX + mov ah, 01 + movd mm1, eax ; save CPU pkg count into MM1[15:8] + + RET_ESI + +DetectNumOfCPUSocket ENDP + +; STATUS_CODE (07h) +VeryEarlyMicrocodeUpdate PROC NEAR PRIVATE + +IF EARLY_MICROCODE_SUPPORT + mov ecx, IA32_BIOS_SIGN_ID + rdmsr ; CPU PatchID -> EDX + cmp edx, 0 ; If microcode has been updated + jnz luExit ; Skip if patch already loaded + + mov ecx, IA32_PLATFORM_ID ; To get Platform ID. + rdmsr + shr edx, 18 ; EDX[0-2] = Platform ID. + and dx, 07h ; DX = Platform ID. + mov si, dx ; Save Platform ID in FS. + mov eax, 01h ; To get CPU signature. + cpuid ; EAX = CPU signature. + mov cx, si ; CX = Platform ID + xor edx, edx + bts dx, cx ; EDX = Platform ID bit. + +; mov esi, PcdGet32 (PcdFlashMicrocodeFvBase) + mov esi, MICROCODE_FV_BASE_ADDRESS + + mov ebx, esi + mov bx, FVHEADER_LEN_OFF + movzx ebx, WORD PTR [ebx] + add esi, ebx + add si, FFSHEADER_LEN ; add FFS header + +; mov edi, PcdGet32 (PcdFlashMicrocodeFvBase) +; mov ebx, PcdGet32 (PcdFlashMicrocodeFvSize) + mov edi, MICROCODE_FV_BASE_ADDRESS + mov ebx, MICROCODE_FV_SIZE + add edi, ebx ;End addr of uCodes. + + ; EAX = CPU signature. + ; EDX = Platform ID bit. + ; ESI = Abs addr of contiguous uCode blocks. + ; EDI = Abs addr of contiguous uCode blocks end. + +luCheckPatch: + cmp (UpdateHeaderStruc PTR ds:[esi]).dProcessorSignature, eax;Sig matched? + jnz luCheckUnprogrammed ; No. + test (UpdateHeaderStruc PTR ds:[esi]).dProcessorFlags, edx;Platform matched? + jnz luFoundMatch ; Yes. + +luCheckUnprogrammed: + mov ebx, (UpdateHeaderStruc PTR ds:[esi]).dDataSize + cmp ebx, 0FFFFFFFFh + je luUnprogrammed + cmp (UpdateHeaderStruc PTR ds:[esi]).dLoaderRevision, 1 + je luCheckExtdHdrs + +luUnprogrammed: + mov ebx, 1024 ; Unprogrammed space, 1KB checks + jmp luPoinToNextBlock ; for backword compatibility. + +luCheckExtdHdrs: + add ebx, SIZEOF(UpdateHeaderStruc) + cmp ebx, (UpdateHeaderStruc PTR ds:[esi]).dTotalSize + jae luTryNextPatch ; No extd hdrs. + + mov ecx, DWORD PTR ds:[esi + ebx] + jcxz luTryNextPatch ; No extd hdrs. (OK to use CX instead of ECX). + add ebx, 20 ; Point to the first Extd Sig. +luNextSig: + cmp eax, DWORD PTR ds:[esi + ebx] ;Sig matched? + jne lu_00 + test edx, DWORD PTR ds:[esi + ebx + 4] ;Platform matched? + jnz luFoundMatch +lu_00: + add ebx, 12 + loop luNextSig + +luTryNextPatch: + mov ebx, (UpdateHeaderStruc PTR ds:[esi]).dTotalSize + or ebx, ebx + jnz luPoinToNextBlock ; Variable size uCode format. + mov ebx, BLOCK_LENGTH_BYTES ; Fixed size uCode format. + +; +; Add alignment check - begin +; + test ebx, 0400h + jz @F + add ebx, 0400h +@@: +; +; Add alignment check - end +; + +luPoinToNextBlock: + add esi, ebx + cmp esi, edi + jb luCheckPatch ; Check with all patches. + + ; Check possible multiple patch + movd eax, mm3 + movd esi, mm4 + or eax, eax + jnz luLoadPatch + jmp luExit ; No matching patch found. + +luFoundMatch: +; MM3 = Patch Revision +; MM4 = Patch Pointer + movd ebx, mm3 + cmp (UpdateHeaderStruc PTR ds:[esi]).dUpdateRevision, ebx + jb luTryNextPatch + + mov ebx, (UpdateHeaderStruc PTR ds:[esi]).dUpdateRevision + +luStoreRevPtr: + movd mm3, ebx ; save Patch Revision + movd mm4, esi ; save Patch Pointer + jmp luTryNextPatch + +luLoadPatch: + mov ecx, IA32_BIOS_UPDT_TRIG + mov eax, esi ; EAX - Abs addr of uCode patch. + add eax, SIZEOF(UpdateHeaderStruc) ; EAX - Abs addr of uCode data. + xor edx, edx ; EDX:EAX - Abs addr of uCode data. + wrmsr ; Trigger uCode load. + +luExit: + +ENDIF + + RET_EBP +VeryEarlyMicrocodeUpdate ENDP + + +; STATUS_CODE (09h) +;************************************************************ +; Description: +; +; This function initializes the Cache for Data, Stack, and Code +; as specified in the BIOS Writer's Guide. +;************************************************************ +InitializeNEM PROC NEAR PRIVATE +IFDEF BOOT_GUARD_SUPPORT_FLAG + ; + ; Detect Boot Guard Boot + ; + mov ecx, MSR_BOOT_GUARD_SACM_INFO ; + rdmsr + and eax, 01h + jnz BootGuardNemSetup +ENDIF + + ; + ; Enable cache for use as stack and for caching code + ; The algorithm is specified in the processor BIOS writer's guide + ; + + ; + ; Ensure that the system is in flat 32 bit protected mode. + ; + ; Platform Specific - configured earlier + ; + ; Ensure that only one logical processor in the system is the BSP. + ; (Required step for clustered systems). + ; + ; Platform Specific - configured earlier + + ; Ensure all APs are in the Wait for SIPI state. + ; This includes all other logical processors in the same physical processor + ; as the BSP and all logical processors in other physical processors. + ; If any APs are awake, the BIOS must put them back into the Wait for + ; SIPI state by issuing a broadcast INIT IPI to all excluding self. + ; + mov edi, APIC_ICR_LO ; 0FEE00300h - Send INIT IPI to all excluding self + mov eax, ORAllButSelf + ORSelfINIT ; 0000C4500h + mov [edi], eax + +@@: + mov eax, [edi] + bt eax, 12 ; Check if send is in progress + jc @B ; Loop until idle + + ; + ; Load microcode update into BSP. + ; + ; Ensure that all variable-range MTRR valid flags are clear and + ; IA32_MTRR_DEF_TYPE MSR E flag is clear. Note: This is the default state + ; after hardware reset. + ; + ; Platform Specific - MTRR are usually in default state. + ; + + ; + ; Initialize all fixed-range and variable-range MTRR register fields to 0. + ; + mov ecx, IA32_MTRR_CAP ; get variable MTRR support + rdmsr + movzx ebx, al ; EBX = number of variable MTRR pairs + shl ebx, 2 ; *4 for Base/Mask pair and WORD size + add ebx, MtrrCountFixed * 2 ; EBX = size of Fixed and Variable MTRRs + + xor eax, eax ; Clear the low dword to write + xor edx, edx ; Clear the high dword to write + ;;;mov ebx, MtrrCount * 2 ; ebx <- sizeof MtrrInitTable +InitMtrrLoop: + add ebx, -2 + movzx ecx, WORD PTR cs:MtrrInitTable[ebx] ; ecx <- address of mtrr to zero + wrmsr + jnz InitMtrrLoop ; loop through the whole table + + ; + ; Configure the default memory type to un-cacheable (UC) in the + ; IA32_MTRR_DEF_TYPE MSR. + ; + mov ecx, MTRR_DEF_TYPE ; Load the MTRR default type index + rdmsr + and eax, NOT (00000CFFh) ; Clear the enable bits and def type UC. + wrmsr + + ; Configure MTRR_PHYS_MASK_HIGH for proper addressing above 4GB + ; based on the physical address size supported for this processor + ; This is based on read from CPUID EAX = 080000008h, EAX bits [7:0] + ; + ; Examples: + ; MTRR_PHYS_MASK_HIGH = 00000000Fh For 36 bit addressing + ; MTRR_PHYS_MASK_HIGH = 0000000FFh For 40 bit addressing + ; + mov eax, 80000008h ; Address sizes leaf + cpuid + sub al, 32 + movzx eax, al + xor esi, esi + bts esi, eax + dec esi ; esi <- MTRR_PHYS_MASK_HIGH + + ; + ; Configure the DataStack region as write-back (WB) cacheable memory type + ; using the variable range MTRRs. + ; + + ; + ; Set the base address of the DataStack cache range + ; +; mov eax, PcdGet32 (PcdTemporaryRamBase) + mov eax, TEMPORARY_RAM_BASE_ADDRESS + or eax, MTRR_MEMORY_TYPE_WB + ; Load the write-back cache value + xor edx, edx ; clear upper dword + mov ecx, MTRR_PHYS_BASE_0 ; Load the MTRR index + wrmsr ; the value in MTRR_PHYS_BASE_0 + + ; + ; Set the mask for the DataStack cache range + ; Compute MTRR mask value: Mask = NOT (Size - 1) + ; +; mov eax, PcdGet32 (PcdTemporaryRamSize) + mov eax, TEMPORARY_RAM_SIZE + dec eax + not eax + or eax, MTRR_PHYS_MASK_VALID + ; turn on the Valid flag + mov edx, esi ; edx <- MTRR_PHYS_MASK_HIGH + mov ecx, MTRR_PHYS_MASK_0 ; For proper addressing above 4GB + wrmsr ; the value in MTRR_PHYS_BASE_0 + + ; + ; Configure the BIOS code region as write-protected (WP) cacheable + ; memory type using a single variable range MTRR. + ; + ; Platform Specific - ensure region to cache meets MTRR requirements for + ; size and alignment. + ; + + ; + ; Save MM5 into ESP before program MTRR, because program MTRR will use MM5 as the local variable. + ; And, ESP is not initialized before CAR is enabled. So, it is safe ot use ESP here. + ; + movd esp, mm5 + + ; + ; Get total size of cache from PCD if it need fix value + ; +; mov eax, PcdGet32 (PcdNemCodeCacheSize) + mov eax, CODE_CACHE_SIZE + ; + ; Calculate NEM size + ; Determine LLC size by following RS - Haswell Processor Family BIOS Writer's Guide (BWG) 0.3.0 + ; Section 4.4.5 - The size of the code region and data region combined must not exceed the size + ; of the (Last Level Cache - 0.5MB). + ; + ; Determine Cache Parameter by CPUID Function 04h + ; + xor ecx, ecx + xor edi, edi + +Find_LLC_parameter: + mov ecx, edi + mov eax, 4 + cpuid + inc edi + and eax, 01Fh ; If EAX[4:0]=0, which indicates no more caches, then we can get LLC parameters + jnz Find_LLC_parameter + ; + ; LLC configuration is pointed to edi-2 + ; + dec edi + dec edi + mov ecx, edi + mov eax, 4 + cpuid + ; + ; Got LLC parameters + ; + ; This Cache Size in Bytes = (Ways + 1) * (Partitions + 1) * (Line_Size + 1) * (Sets + 1) + ; = (EBX[31:22] + 1) * (EBX[21:12] + 1) * (EBX[11:0] + 1) * (ECX + 1) + ; + mov eax, ecx + inc eax + mov edi, ebx + shr ebx, 22 + inc ebx + mul ebx + mov ebx, edi + and ebx, NOT 0FFC00FFFh + shr ebx, 12 + inc ebx + mul ebx + mov ebx, edi + and ebx, 0FFFh + inc ebx + mul ebx + ; + ; Maximum NEM size <= (Last Level Cache - 0.5MB) + ; + sub eax, 512*1024 +Got_NEM_size: + ; + ; Code cache size = Total NEM size - DataStack size + ; +; sub eax, PcdGet32 (PcdTemporaryRamSize) + sub eax, TEMPORARY_RAM_SIZE + ; + ; Set the base address of the CodeRegion cache range from PCD + ; PcdNemCodeCacheBase is set to the offset to flash base, + ; so add PcdFlashAreaBaseAddress to get the real code base address. + ; +; mov edi, PcdGet32 (PcdNemCodeCacheBase) +; add edi, PcdGet32 (PcdFlashAreaBaseAddress) + mov edi, CODE_CACHE_BASE_ADDRESS + add edi, FLASH_AREA_BASE_ADDRESS + + ; + ; Round up to page size + ; + mov ecx, eax ; Save + and ecx, 0FFFF0000h ; Number of pages in 64K + and eax, 0FFFFh ; Number of "less-than-page" bytes + jz Rounded + mov eax, 10000h ; Add the whole page size + +Rounded: + add eax, ecx ; eax - rounded up code cache size + + ; + ; Define "local" vars for this routine + ; Note that mm0 is used to store BIST result for BSP, + ; mm1 is used to store the number of processor and BSP APIC ID, + ; mm6 is used to save time-stamp counter value. + ; + CODE_SIZE_TO_CACHE TEXTEQU <mm3> + CODE_BASE_TO_CACHE TEXTEQU <mm4> + NEXT_MTRR_INDEX TEXTEQU <mm5> + NEXT_MTRR_SIZE TEXTEQU <mm2> + ; + ; Initialize "locals" + ; + sub ecx, ecx + movd NEXT_MTRR_INDEX, ecx ; Count from 0 but start from MTRR_PHYS_BASE_1 + + ; + ; Save remaining size to cache + ; + movd CODE_SIZE_TO_CACHE, eax ; Size of code cache region that must be cached + movd CODE_BASE_TO_CACHE, edi ; Base code cache address + +NextMtrr: + ; + ; Get remaining size to cache + ; + movd eax, CODE_SIZE_TO_CACHE + and eax, eax + jz CodeRegionMtrrdone ; If no left size - we are done + ; + ; Determine next size to cache. + ; We start from bottom up. Use the following algorythm: + ; 1. Get our own alignment. Max size we can cache equals to our alignment + ; 2. Determine what is bigger - alignment or remaining size to cache. + ; If aligment is bigger - cache it. + ; Adjust remaing size to cache and base address + ; Loop to 1. + ; If remaining size to cache is bigger + ; Determine the biggest 2^N part of it and cache it. + ; Adjust remaing size to cache and base address + ; Loop to 1. + ; 3. End when there is no left size to cache or no left MTRRs + ; + movd edi, CODE_BASE_TO_CACHE + bsf ecx, edi ; Get index of lowest bit set in base address + ; + ; Convert index into size to be cached by next MTRR + ; + mov edx, 1h + shl edx, cl ; Alignment is in edx + cmp edx, eax ; What is bigger, alignment or remaining size? + jbe gotSize ; JIf aligment is less + ; + ; Remaining size is bigger. Get the biggest part of it, 2^N in size + ; + bsr ecx, eax ; Get index of highest set bit + ; + ; Convert index into size to be cached by next MTRR + ; + mov edx, 1 + shl edx, cl ; Size to cache + +GotSize: + mov eax, edx + movd NEXT_MTRR_SIZE, eax ; Save + + ; + ; Compute MTRR mask value: Mask = NOT (Size - 1) + ; + dec eax ; eax - size to cache less one byte + not eax ; eax contains low 32 bits of mask + or eax, MTRR_PHYS_MASK_VALID ; Set valid bit + + ; + ; Program mask register + ; + mov ecx, MTRR_PHYS_MASK_1 ; setup variable mtrr + movd ebx, NEXT_MTRR_INDEX + add ecx, ebx + + mov edx, esi ; edx <- MTRR_PHYS_MASK_HIGH + wrmsr + ; + ; Program base register + ; + sub edx, edx + mov ecx, MTRR_PHYS_BASE_1 ; setup variable mtrr + add ecx, ebx ; ebx is still NEXT_MTRR_INDEX + + movd eax, CODE_BASE_TO_CACHE + or eax, MTRR_MEMORY_TYPE_WP ; set type to write protect + wrmsr + ; + ; Advance and loop + ; Reduce remaining size to cache + ; + movd ebx, CODE_SIZE_TO_CACHE + movd eax, NEXT_MTRR_SIZE + sub ebx, eax + movd CODE_SIZE_TO_CACHE, ebx + + ; + ; Increment MTRR index + ; + movd ebx, NEXT_MTRR_INDEX + add ebx, 2 + movd NEXT_MTRR_INDEX, ebx + ; + ; Increment base address to cache + ; + movd ebx, CODE_BASE_TO_CACHE + movd eax, NEXT_MTRR_SIZE + add ebx, eax + ; + ; if carry happens, means NEM base + size over 4G + ; + jc CodeRegionMtrrdone + movd CODE_BASE_TO_CACHE, ebx + + jmp NextMtrr + +CodeRegionMtrrdone: + ; Program the variable MTRR's MASK register for WDB + ; (Write Data Buffer, used in MRC, must be WC type) + ; + mov ecx, MTRR_PHYS_MASK_1 + movd ebx, NEXT_MTRR_INDEX + add ecx, ebx + mov edx, esi ; edx <- MTRR_PHYS_MASK_HIGH + mov eax, WDB_REGION_SIZE_MASK OR MTRR_PHYS_MASK_VALID ; turn on the Valid flag + wrmsr + + ; + ; Program the variable MTRR's BASE register for WDB + ; + dec ecx + xor edx, edx + mov eax, WDB_REGION_BASE_ADDRESS OR MTRR_MEMORY_TYPE_WC + wrmsr + + ; + ; Enable the MTRRs by setting the IA32_MTRR_DEF_TYPE MSR E flag. + ; + mov ecx, MTRR_DEF_TYPE ; Load the MTRR default type index + rdmsr + or eax, MTRR_DEF_TYPE_E ; Enable variable range MTRRs + wrmsr + + ; + ; Enable the logical processor's (BSP) cache: execute INVD and set + ; CR0.CD = 0, CR0.NW = 0. + ; + mov eax, cr0 + and eax, NOT (CR0_CACHE_DISABLE + CR0_NO_WRITE) + invd + mov cr0, eax + ; + ; Enable No-Eviction Mode Setup State by setting + ; NO_EVICT_MODE MSR 2E0h bit [0] = '1'. + ; + mov ecx, NO_EVICT_MODE + rdmsr + or eax, 1 + wrmsr + + ; + ; Restore MM5 from ESP after program MTRR + ; + movd mm5, esp + + ; + ; One location in each 64-byte cache line of the DataStack region + ; must be written to set all cache values to the modified state. + ; +; mov edi, PcdGet32 (PcdTemporaryRamBase) +; mov ecx, PcdGet32 (PcdTemporaryRamSize) + mov edi, TEMPORARY_RAM_BASE_ADDRESS + mov ecx, TEMPORARY_RAM_SIZE + shr ecx, 6 + mov eax, CACHE_INIT_VALUE +@@: + mov [edi], eax + sfence + add edi, 64 + loopd @b + + ; + ; Enable No-Eviction Mode Run State by setting + ; NO_EVICT_MODE MSR 2E0h bit [1] = '1'. + ; + mov ecx, NO_EVICT_MODE + rdmsr + or eax, 2 + wrmsr + +IFDEF BOOT_GUARD_SUPPORT_FLAG + jmp FinishedCacheConfig + + ; + ; Jump to here when Boot Guard boot and NEM is initialized by Boot Guard ACM + ; +BootGuardNemSetup: + ; + ; Finished with cache configuration + ; + ; Configure MTRR_PHYS_MASK_HIGH for proper addressing above 4GB + ; based on the physical address size supported for this processor + ; This is based on read from CPUID EAX = 080000008h, EAX bits [7:0] + ; + ; Examples: + ; MTRR_PHYS_MASK_HIGH = 00000000Fh For 36 bit addressing + ; MTRR_PHYS_MASK_HIGH = 0000000FFh For 40 bit addressing + ; + mov eax, 80000008h ; Address sizes leaf + cpuid + sub al, 32 + movzx eax, al + xor esi, esi + bts esi, eax + dec esi ; esi <- MTRR_PHYS_MASK_HIGH + + ; + ; Configure the DataStack region as write-back (WB) cacheable memory type + ; using the variable range MTRRs. + ; + ; + ; Find available MTRR + ; + CALL_EBP FindFreeMtrr + + ; + ; Set the base address of the DataStack cache range + ; +; mov eax, PcdGet32 (PcdTemporaryRamBase) + mov eax, TEMPORARY_RAM_BASE_ADDRESS + or eax, MTRR_MEMORY_TYPE_WB + ; Load the write-back cache value + xor edx, edx ; clear upper dword + wrmsr ; the value in MTRR_PHYS_BASE_0 + + ; + ; Set the mask for the DataStack cache range + ; Compute MTRR mask value: Mask = NOT (Size - 1) + ; +; mov eax, PcdGet32 (PcdTemporaryRamSize) + mov eax, TEMPORARY_RAM_SIZE + dec eax + not eax + or eax, MTRR_PHYS_MASK_VALID + ; turn on the Valid flag + mov edx, esi ; edx <- MTRR_PHYS_MASK_HIGH + inc ecx + wrmsr ; the value in MTRR_PHYS_BASE_0 + + ; + ; Program the variable MTRR's MASK register for WDB + ; (Write Data Buffer, used in MRC, must be WC type) + ; + + ; + ; Find available MTRR + ; + CALL_EBP FindFreeMtrr + +FoundAvailableMtrr: + ; + ; Program the variable MTRR's BASE register for WDB + ; + xor edx, edx + mov eax, WDB_REGION_BASE_ADDRESS OR MTRR_MEMORY_TYPE_WC + wrmsr + + inc ecx + mov edx, esi ; edx <- MTRR_PHYS_MASK_HIGH + mov eax, WDB_REGION_SIZE_MASK OR MTRR_PHYS_MASK_VALID ; turn on the Valid flag + wrmsr + + ; + ; One location in each 64-byte cache line of the DataStack region + ; must be written to set all cache values to the modified state. + ; +; mov edi, PcdGet32 (PcdTemporaryRamBase) +; mov ecx, PcdGet32 (PcdTemporaryRamSize) + mov edi, TEMPORARY_RAM_BASE_ADDRESS + mov ecx, TEMPORARY_RAM_SIZE + shr ecx, 6 + mov eax, CACHE_INIT_VALUE +@@: + mov [edi], eax + sfence + add edi, 64 + loopd @b +ENDIF + + ; + ; Finished with cache configuration + ; +FinishedCacheConfig: + + ; + ; Optionally Test the Region... + ; + + ; + ; Test area by writing and reading + ; + cld +; mov edi, PcdGet32 (PcdTemporaryRamBase) +; mov ecx, PcdGet32 (PcdTemporaryRamSize) + mov edi, TEMPORARY_RAM_BASE_ADDRESS + mov ecx, TEMPORARY_RAM_SIZE + shr ecx, 2 + mov eax, CACHE_TEST_VALUE +TestDataStackArea: + stosd + cmp eax, DWORD PTR [edi-4] + jnz DataStackTestFail + loop TestDataStackArea + jmp DataStackTestPass + + ; + ; Cache test failed + ; +DataStackTestFail: + STATUS_CODE (0D0h) + jmp $ + + ; + ; Configuration test failed + ; +ConfigurationTestFailed: + STATUS_CODE (0D1h) + jmp $ + +DataStackTestPass: + + ; + ; At this point you may continue normal execution. Typically this would include + ; reserving stack, initializing the stack pointer, etc. + ; + + ; + ; After memory initialization is complete, please follow the algorithm in the BIOS + ; Writer's Guide to properly transition to a normal system configuration. + ; The algorithm covers the required sequence to properly exit this mode. + ; + + RET_ESI + +InitializeNEM ENDP + +; STATUS_CODE (09h) +EstablishStack PROC NEAR PRIVATE + + ; + ; Enable STACK + ; + RET_ESI + +EstablishStack ENDP + +FindFreeMtrr PROC NEAR PRIVATE + mov ecx, MTRR_PHYS_MASK_0 + +@@: + rdmsr + test eax, 800h + jz FoundFreeMtrr + add ecx, 2 + cmp ecx, MTRR_PHYS_MASK_9 + jbe @b + ; + ; No available MTRR, halt system + ; + jmp $ + +FoundFreeMtrr: + dec ecx + + RET_EBP + +FindFreeMtrr ENDP + +; STATUS_CODE (0Bh) +CallPeiCoreEntryPoint PROC NEAR PRIVATE + ; + ; Set stack top pointer + ; +; mov esp, PcdGet32 (PcdTemporaryRamBase) +; add esp, PcdGet32 (PcdTemporaryRamSize) + mov esp, TEMPORARY_RAM_BASE_ADDRESS + add esp, TEMPORARY_RAM_SIZE + + ; + ; Push CPU count to stack first, then AP's (if there is one) + ; BIST status, and then BSP's + ; + + ; + ; Here work around for BIST + ; + ; Get number of BSPs + movd ecx, mm1 + movzx ecx, ch + + ; Save number of BSPs + push ecx + +GetSBSPBist: + ; Save SBSP BIST + movd eax, mm0 + push eax + + ; Save SBSP APIC ID + movd eax, mm1 + shr eax, BSPApicIDSaveStart ; Resume APIC ID + push eax + + ; Save Time-Stamp Counter + movd eax, mm5 + push eax + + movd eax, mm6 + push eax + +TransferToSecStartup: + + + + ; Switch to "C" code + STATUS_CODE (0Ch) + ; + ; Pass entry point of the PEI core + ; + mov edi, PEI_CORE_ENTRY_BASE ; 0FFFFFFE0h + push DWORD PTR ds:[edi] + + ; + ; Pass BFV into the PEI Core + ; + mov edi, FV_MAIN_BASE ; 0FFFFFFFCh + push DWORD PTR ds:[edi] + + ; ECPoverride: SecStartup entry point needs 4 parameters +; push PcdGet32 (PcdTemporaryRamBase) + push TEMPORARY_RAM_BASE_ADDRESS + + ; + ; Pass stack size into the PEI Core + ; +; push PcdGet32 (PcdTemporaryRamSize) + push TEMPORARY_RAM_SIZE + + ; + ; Pass Control into the PEI Core + ; + call SecStartup +CallPeiCoreEntryPoint ENDP + +StartUpAp PROC NEAR + + mov esi, HPET_COMP_2 + lock inc byte ptr [esi] + + DISABLE_CACHE +; +; Halt the AP and wait for the next SIPI +; +Ap_Halt: + cli +@@: + hlt + jmp @B + ret +StartUpAp ENDP + + +CheckValidCMOS PROC NEAR PRIVATE + ; + ; Check CMOS Status + ; + mov esi, PCH_LPC_GEN_PMCON_3_ADDR + mov eax, es:[esi] + + ; check PWR_FLR and RTC_PWR_STS status + and eax, BIT2 + BIT1 + + RET_EBP +CheckValidCMOS ENDP + +MtrrInitTable LABEL BYTE + DW MTRR_DEF_TYPE + DW MTRR_FIX_64K_00000 + DW MTRR_FIX_16K_80000 + DW MTRR_FIX_16K_A0000 + DW MTRR_FIX_4K_C0000 + DW MTRR_FIX_4K_C8000 + DW MTRR_FIX_4K_D0000 + DW MTRR_FIX_4K_D8000 + DW MTRR_FIX_4K_E0000 + DW MTRR_FIX_4K_E8000 + DW MTRR_FIX_4K_F0000 + DW MTRR_FIX_4K_F8000 + +MtrrCountFixed EQU (($ - MtrrInitTable) / 2) + + DW MTRR_PHYS_BASE_0 + DW MTRR_PHYS_MASK_0 + DW MTRR_PHYS_BASE_1 + DW MTRR_PHYS_MASK_1 + DW MTRR_PHYS_BASE_2 + DW MTRR_PHYS_MASK_2 + DW MTRR_PHYS_BASE_3 + DW MTRR_PHYS_MASK_3 + DW MTRR_PHYS_BASE_4 + DW MTRR_PHYS_MASK_4 + DW MTRR_PHYS_BASE_5 + DW MTRR_PHYS_MASK_5 + DW MTRR_PHYS_BASE_6 + DW MTRR_PHYS_MASK_6 + DW MTRR_PHYS_BASE_7 + DW MTRR_PHYS_MASK_7 + DW MTRR_PHYS_BASE_8 + DW MTRR_PHYS_MASK_8 + DW MTRR_PHYS_BASE_9 + DW MTRR_PHYS_MASK_9 +MtrrCount EQU (($ - MtrrInitTable) / 2) + +align 10h +PUBLIC BootGDTtable + +; +; GDT[0]: 0x00: Null entry, never used. +; +NULL_SEL EQU $ - GDT_BASE ; Selector [0] +GDT_BASE: +BootGDTtable DD 0 + DD 0 +; +; Linear data segment descriptor +; +LINEAR_SEL EQU $ - GDT_BASE ; Selector [0x8] + DW 0FFFFh ; limit 0xFFFFF + DW 0 ; base 0 + DB 0 + DB 092h ; present, ring 0, data, expand-up, writable + DB 0CFh ; page-granular, 32-bit + DB 0 +; +; Linear code segment descriptor +; +LINEAR_CODE_SEL EQU $ - GDT_BASE ; Selector [0x10] + DW 0FFFFh ; limit 0xFFFFF + DW 0 ; base 0 + DB 0 + DB 09Bh ; present, ring 0, data, expand-up, not-writable + DB 0CFh ; page-granular, 32-bit + DB 0 +; +; System data segment descriptor +; +SYS_DATA_SEL EQU $ - GDT_BASE ; Selector [0x18] + DW 0FFFFh ; limit 0xFFFFF + DW 0 ; base 0 + DB 0 + DB 093h ; present, ring 0, data, expand-up, not-writable + DB 0CFh ; page-granular, 32-bit + DB 0 + +; +; System code segment descriptor +; +SYS_CODE_SEL EQU $ - GDT_BASE ; Selector [0x20] + DW 0FFFFh ; limit 0xFFFFF + DW 0 ; base 0 + DB 0 + DB 09Ah ; present, ring 0, data, expand-up, writable + DB 0CFh ; page-granular, 32-bit + DB 0 +; +; Spare segment descriptor +; +SYS16_CODE_SEL EQU $ - GDT_BASE ; Selector [0x28] + DW 0FFFFh ; limit 0xFFFFF + DW 0 ; base 0 + DB 0Eh ; Changed from F000 to E000. + DB 09Bh ; present, ring 0, code, expand-up, writable + DB 00h ; byte-granular, 16-bit + DB 0 +; +; Spare segment descriptor +; +SYS16_DATA_SEL EQU $ - GDT_BASE ; Selector [0x30] + DW 0FFFFh ; limit 0xFFFF + DW 0 ; base 0 + DB 0 + DB 093h ; present, ring 0, data, expand-up, not-writable + DB 00h ; byte-granular, 16-bit + DB 0 + +; +; Spare segment descriptor +; +SPARE5_SEL EQU $ - GDT_BASE ; Selector [0x38] + DW 0 ; limit 0 + DW 0 ; base 0 + DB 0 + DB 0 ; present, ring 0, data, expand-up, writable + DB 0 ; page-granular, 32-bit + DB 0 +GDT_SIZE EQU $ - BootGDTtable ; Size, in bytes + +GdtDesc: ; GDT descriptor +OffsetGDTDesc EQU $ - _ModuleEntryPoint + DW GDT_SIZE - 1 ; GDT limit + DD OFFSET BootGDTtable ; GDT base address + +NemInitLinearAddress LABEL FWORD +NemInitLinearOffset LABEL DWORD + DD OFFSET ProtectedModeSECStart ; Offset of our 32 bit code + DW LINEAR_CODE_SEL + +TopOfCar DD TEMPORARY_RAM_BASE_ADDRESS + TEMPORARY_RAM_SIZE + +_TEXT_PROTECTED_MODE ENDS +END diff --git a/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/Ia32.inc b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/Ia32.inc new file mode 100644 index 0000000..d799a1e --- /dev/null +++ b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/Ia32.inc @@ -0,0 +1,164 @@ +;@file +; IA32 architecture MSRs +; +;@copyright +; Copyright (c) 1999 - 2013 Intel Corporation. All rights reserved +; This software and associated documentation (if any) is furnished +; under a license and may only be used or copied in accordance +; with the terms of the license. Except as permitted by such +; license, no part of this software or documentation may be +; reproduced, stored in a retrieval system, or transmitted in any +; form or by any means without the express written consent of +; Intel Corporation. +; +; This file contains a 'Sample Driver' and is licensed as such +; under the terms of your license agreement with Intel or your +; vendor. This file may be modified by the user, subject to +; the additional terms of the license agreement +; + +IA32_MTRR_CAP EQU 0FEh +MTRR_PHYS_BASE_0 EQU 0200h +MTRR_PHYS_MASK_0 EQU 0201h +MTRR_PHYS_BASE_1 EQU 0202h +MTRR_PHYS_MASK_1 EQU 0203h +MTRR_PHYS_BASE_2 EQU 0204h +MTRR_PHYS_MASK_2 EQU 0205h +MTRR_PHYS_BASE_3 EQU 0206h +MTRR_PHYS_MASK_3 EQU 0207h +MTRR_PHYS_BASE_4 EQU 0208h +MTRR_PHYS_MASK_4 EQU 0209h +MTRR_PHYS_BASE_5 EQU 020Ah +MTRR_PHYS_MASK_5 EQU 020Bh +MTRR_PHYS_BASE_6 EQU 020Ch +MTRR_PHYS_MASK_6 EQU 020Dh +MTRR_PHYS_BASE_7 EQU 020Eh +MTRR_PHYS_MASK_7 EQU 020Fh +MTRR_PHYS_BASE_8 EQU 0210h +MTRR_PHYS_MASK_8 EQU 0211h +MTRR_PHYS_BASE_9 EQU 0212h +MTRR_PHYS_MASK_9 EQU 0213h +MTRR_FIX_64K_00000 EQU 0250h +MTRR_FIX_16K_80000 EQU 0258h +MTRR_FIX_16K_A0000 EQU 0259h +MTRR_FIX_4K_C0000 EQU 0268h +MTRR_FIX_4K_C8000 EQU 0269h +MTRR_FIX_4K_D0000 EQU 026Ah +MTRR_FIX_4K_D8000 EQU 026Bh +MTRR_FIX_4K_E0000 EQU 026Ch +MTRR_FIX_4K_E8000 EQU 026Dh +MTRR_FIX_4K_F0000 EQU 026Eh +MTRR_FIX_4K_F8000 EQU 026Fh +MTRR_DEF_TYPE EQU 02FFh + +MTRR_MEMORY_TYPE_UC EQU 00h +MTRR_MEMORY_TYPE_WC EQU 01h +MTRR_MEMORY_TYPE_WT EQU 04h +MTRR_MEMORY_TYPE_WP EQU 05h +MTRR_MEMORY_TYPE_WB EQU 06h + +MTRR_DEF_TYPE_E EQU 0800h +MTRR_DEF_TYPE_FE EQU 0400h +MTRR_PHYSMASK_VALID EQU 0800h + +; +; Define the high 32 bits of MTRR masking +; This should be read from CPUID EAX = 080000008h, EAX bits [7:0] +; But for most platforms this will be a fixed supported size so it is +; fixed to save space. +; +MTRR_PHYS_MASK_VALID EQU 0800h +MTRR_PHYS_MASK_HIGH EQU 00000000Fh ; For 36 bit addressing +;MTRR_PHYS_MASK_HIGH EQU 0000000FFh ; For 40 bit addressing + +IA32_MISC_ENABLE EQU 1A0h +FAST_STRING_ENABLE_BIT EQU 01h + +CR0_CACHE_DISABLE EQU 040000000h +CR0_NO_WRITE EQU 020000000h + +IA32_PLATFORM_ID EQU 017h +IA32_BIOS_UPDT_TRIG EQU 079h +IA32_BIOS_SIGN_ID EQU 08Bh +PLATFORM_INFO EQU 0CEh +NO_EVICT_MODE EQU 2E0h +NO_EVICTION_ENABLE_BIT EQU 01h + +; +; MSR definitions +; +MSR_IA32_PLATFORM_ID EQU 0017h +MSR_APIC_BASE EQU 001Bh +MSR_SOCKET_ID EQU 0039h +MSR_IA32_FEATURE_CONTROL EQU 003Ah +MSR_CLOCK_CST_CONFIG_CONTROL EQU 00E2h +MSR_CLOCK_FLEX_MAX EQU 0194h +MSR_IA32_PERF_STS EQU 0198h +MSR_IA32_PERF_CTL EQU 0199h +MSR_IA32_MISC_ENABLES EQU 01A0h +MSR_IA32_MC8_MISC2 EQU 0288h +MSR_IA32_MC7_CTL EQU 041Ch +MSR_BOOT_GUARD_SACM_INFO EQU 013Ah + +; +; Processor MSR definitions +; +MSR_BBL_CR_CTL3 EQU 011Eh ; L2 cache configuration MSR +B_MSR_BBL_CR_CTL3_L2_NOT_PRESENT EQU 23 ; L2 not present +B_MSR_BBL_CR_CTL3_L2_ENABLED EQU 8 ; L2 enabled +B_MSR_BBL_CR_CTL3_L2_HARDWARE_ENABLED EQU 0 ; L2 hardware enabled + +P6RatioBitsMask EQU 01Fh ; Bitmask for cpu ratio +P6_FREQ_LOCKED_BIT EQU 15d + +; +; Local APIC Register Equates +; +LOCAL_APIC_ID_REG EQU 0FEE00020h +APIC_ICR_HI EQU 0FEE00310h +APIC_ICR_LO EQU 0FEE00300h +ANDICRMask EQU 0FFF32000h ; AND mask for ICR Saving reserved bits +ORSelfINIT EQU 000004500h ; OR mask to send INIT IPI to itself +ORAllButSelf EQU 0000C0000h ; OR mask to set dest field = "All But Self" + +; +; Cache control macro +; +DISABLE_CACHE macro + mov eax, cr0 + or eax, CR0_CACHE_DISABLE + CR0_NO_WRITE + wbinvd + mov cr0, eax +endm + +ENABLE_CACHE macro + mov eax, cr0 + and eax, NOT (CR0_CACHE_DISABLE + CR0_NO_WRITE) + wbinvd + mov cr0, eax +endm + +VENDOR_ID_REG EQU 0 +PCI_REVISION_ID_REG EQU 8 +CPU_GENERIC_UNCORE_DEV EQU 0 +CPU_GENERIC_UNCORE_FUNC EQU 0 +CPU_LINK_1_DEV EQU 2 +CPU_LINK_1_FUNC EQU 4 + +B0_CPU_STEPPING EQU 10h + +BLOCK_LENGTH_BYTES EQU 2048 + +UpdateHeaderStruc STRUC + dHeaderVersion dd ? ; Header version# + dUpdateRevision dd ? ; Update revision# + dDate dd ? ; Date in binary (08/13/07 as 0x08132007) + dProcessorSignature dd ? ; CPU type, family, model, stepping + dChecksum dd ? ; Checksum + dLoaderRevision dd ? ; Update loader version# + dProcessorFlags dd ? ; Processor Flags + dDataSize dd ? ; Size of encrypted data + dTotalSize dd ? ; Total size of update in bytes + bReserved db 12 dup(?) ; 12 bytes reserved +UpdateHeaderStruc ENDS + diff --git a/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/Platform.inc b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/Platform.inc new file mode 100644 index 0000000..b49f518 --- /dev/null +++ b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/Platform.inc @@ -0,0 +1,196 @@ +;@file +; Platform Specific Definitions +; +;@copyright +; Copyright (c) 2011 - 2012 Intel Corporation. All rights reserved +; This software and associated documentation (if any) is furnished +; under a license and may only be used or copied in accordance +; with the terms of the license. Except as permitted by such +; license, no part of this software or documentation may be +; reproduced, stored in a retrieval system, or transmitted in any +; form or by any means without the express written consent of +; Intel Corporation. +; +; This file contains an 'Intel Peripheral Driver' and uniquely +; identified as "Intel Reference Module" and is +; licensed for Intel CPUs and chipsets under the terms of your +; license agreement with Intel or your vendor. This file may +; be modified by the user, subject to additional terms of the +; license agreement +; + +;(AMI_CHG-)INCLUDE FlashMap.inc + +; Set "MINIMUM_BOOT_SUPPORT" flag allows BIOS boot as minimum feature in SEC phase. +MINIMUM_BOOT_SUPPORT EQU 0 ; ="0", Normal Boot; + ; ="1", Minimum Feature Boot +; "RESET_IN_SEC" flag allows BIOS doing RESET in SEC phase +RESET_IN_SEC EQU 0 ; ="0", RESET occurs in OemIohInit.c + ; ="1", RESET occurs in SEC phase + +EARLY_MICROCODE_SUPPORT EQU 1 +DETERMINISTIC_BSP_SUPPORT EQU 0 +DEBUG EQU 1 + +; +; IO port to access the upper 128-byte of RTC RAM +; +RTC_UPPER_INDEX EQU 072h +RTC_UPPER_DATA EQU 073h + +; +; Offset of data stored in the upper 128-byte of RTC RAM. +; +CMOS_CPU_BSP_SELECT EQU 010h ; BspSelection +CMOS_CPU_UP_MODE EQU 011h ; UpBootSelection + +; +; Cpu Ratio and Vid stored in the upper 128-byte of RTC RAM. +; +CMOS_CPU_RATIO_OFFSET EQU 012h ; ProcessorFlexibleRatio +CMOS_CPU_CORE_HT_OFFSET EQU 013h ; ProcessorHyperThreadingEnable & EnableCoresInSbsp & EnableCoresInNbsp + +; +; CPU Feature +; +CMOS_CPU_BIST_OFFSET EQU 015h ; ProcessorBistEnable +CMOS_CPU_VMX_OFFSET EQU 016h ; ProcessorVmxEnable + +; +; Port80 Selection +; +CMOS_PCH_PORT80_OFFSET EQU 017h ; PchPort80Route + +; +;Flash layout map +; +PEICODE_REGION_BASE_ADDRESS EQU FLASH_BASE +PEICODE_REGION_SIZE EQU FLASH_SIZE +PEICODE_REGION_SIZE_MASK EQU (NOT (PEICODE_REGION_SIZE - 1)) + +BIOS_REGION_UPDATABLE_STATUS EQU 0058h ; Offset +;---------------------------------------------------------------------------------------- +; "Merlin" support used equates +;---------------------------------------------------------------------------------------- +MAGIC_ADDRESS_IN_SEG EQU 0FFF0h +MAGIC_SEG EQU 0F000h + +; +; -- Equates for CAR initialization +; TileSize (must be a power of 2) +; +; Define the tile size +; The tile size and tile placement are critical to ensuring that no data loss occurs +; See BWG - chapter "Determining Tile Size" +; +TILE_SIZE EQU 000000000h + +; +; See BWG - chapter "Determining Cacheable Code Region Base Addresses and Ranges". +; +; Now FvRecovery is 6 blocks, so it is seperated into 2 parts to set MTRR: +; 1. base address = FFFA0000, length = 0x20000 +; 2. base address = FFFC0000, length = 0x40000 +; +; *** NOTE: If FvRecovery size changes, this code needs to be changed accordingly. +; Possible enhancement is to dynamically accomodate size changes. +; + +;(AMI_CHG)> +;-CODE_REGION_BASE_ADDRESS_PART1 EQU FLASH_REGION_FV_RECOVERY_BASE +;-CODE_REGION_SIZE_PART1 EQU (TILE_SIZE + (128*1024)) + +MIN_CODE_REGION_SIZE EQU 40000h +MIN_CODE_REGION_SIZE_MASK EQU (NOT (MIN_CODE_REGION_SIZE - 1)) +CODE_REGION_BASE_ADDRESS_PART1 EQU MKF_CODE_CACHE_BASE_ADDRESS AND 0ffff0000h +IF MKF_CODE_CACHE_SIZE lt 100000h + CODE_REGION_SIZE_PART1 EQU 100000h +ELSE + CODE_REGION_SIZE_PART1 EQU MKF_CODE_CACHE_SIZE +ENDIF + +CODE_REGION_SIZE_MASK_PART1 EQU (NOT (CODE_REGION_SIZE_PART1 - 1)) + +IF MKF_CODE_CACHE_PART2_BASE +;-CODE_REGION_BASE_ADDRESS_PART2 EQU CODE_REGION_BASE_ADDRESS_PART1 + CODE_REGION_SIZE_PART1 +;-CODE_REGION_SIZE_PART2 EQU (TILE_SIZE + (256*1024)) +CODE_REGION_BASE_ADDRESS_PART2 EQU MKF_CODE_CACHE_PART2_BASE +CODE_REGION_SIZE_PART2 EQU MKF_CODE_CACHE_PART2_SIZE +CODE_REGION_SIZE_MASK_PART2 EQU (NOT (CODE_REGION_SIZE_PART2 - 1)) +ENDIF + +IF MKF_WDB_REGION_BASE_ADDRESS +;-WDB_REGION_BASE_ADDRESS EQU 040000000h +;-WDB_REGION_SIZE EQU 01000h +WDB_REGION_BASE_ADDRESS EQU MKF_WDB_REGION_BASE_ADDRESS +WDB_REGION_SIZE EQU MKF_WDB_REGION_BASE_SIZE +WDB_REGION_SIZE_MASK EQU (NOT (WDB_REGION_SIZE - 1)) +ENDIF +;<(AMI_CHG) + +; +; See BWG - chapter "Determining Data Stack Base Address and Range" +; +;(AMI_CHG)> +;-;DATA_STACK_BASE_ADDRESS EQU (CODE_REGION_BASE_ADDRESS - TILE_SIZE - (16*1024 * 1024)) +;-DATA_STACK_BASE_ADDRESS EQU 0FFB00000h +;-DATA_STACK_SIZE EQU (64*1024) ; 10000h +DATA_STACK_BASE_ADDRESS EQU MKF_CAR_BASE_ADDRESS +DATA_STACK_SIZE EQU MKF_CAR_TOTAL_SIZE +DATA_STACK_SIZE_MASK EQU (NOT (DATA_STACK_SIZE - 1)) +TEMPORARY_RAM_BASE_ADDRESS EQU DATA_STACK_BASE_ADDRESS +TEMPORARY_RAM_SIZE EQU DATA_STACK_SIZE +;<(AMI_CHG) + +; +; Cache init and test values +; These are inverted to flip each bit at least once +; +CACHE_INIT_VALUE EQU 0A5A5A5A5h +CACHE_TEST_VALUE EQU (NOT CACHE_INIT_VALUE) + +PEI_CORE_ENTRY_BASE EQU 0FFFFFFE0h +FV_MAIN_BASE EQU 0FFFFFFFCh + +MAX_NR_BUS EQU 0FFh +MAX_NR_CPU_SOCKETS EQU 2 ; DP example, MP may have 4 or more + +; +; Support EDK1117 build - Sample BASE Address and Size insteads of PcdGet() +; +MICROCODE_FV_BASE_ADDRESS EQU 0FFF20000h ; PcdGet32 (PcdFlashMicrocodeFvBase) +MICROCODE_FV_SIZE EQU 40000h ; PcdGet32 (PcdFlashMicrocodeFvSize) +CODE_CACHE_BASE_ADDRESS EQU 0FFF80000h ; PcdGet32 (PcdNemCodeCacheBase) +CODE_CACHE_SIZE EQU 80000h ; PcdGet32 (PcdNemCodeCacheSize) +FLASH_AREA_BASE_ADDRESS EQU 0FF800000h ; PcdGet32 (PcdFlashAreaBaseAddress) +;(AMI_CHG)> +;TEMPORARY_RAM_BASE_ADDRESS EQU 0FEF00000h ; PcdGet32 (PcdTemporaryRamBase) +;TEMPORARY_RAM_SIZE EQU 2000h ; PcdGet32 (PcdTemporaryRamSize) +;<(AMI_CHG) +PCIEXPRESS_BASE_ADDRESS EQU 0E0000000h ; PcdGet64 (PcdPciExpressBaseAddress) + +BIT0 EQU 01h +BIT1 EQU 02h +BIT2 EQU 04h +BIT3 EQU 08h +BIT4 EQU 10h +BIT5 EQU 20h +BIT6 EQU 40h +BIT7 EQU 80h +BIT8 EQU 100h +BIT9 EQU 200h +BIT10 EQU 400h +BIT11 EQU 800h +BIT12 EQU 1000h +BIT13 EQU 2000h +BIT14 EQU 4000h +BIT15 EQU 8000h +BIT16 EQU 10000h +BIT17 EQU 20000h +BIT18 EQU 40000h +BIT19 EQU 80000h +BIT23 EQU 0800000h +BIT31 EQU 080000000h +; Bit definition in MM1 +BadCMOSDetected EQU (BIT0 shl 17) +BSPApicIDSaveStart EQU 24 diff --git a/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/ResetVec.asm b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/ResetVec.asm new file mode 100644 index 0000000..54376e5 --- /dev/null +++ b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/ResetVec.asm @@ -0,0 +1,108 @@ +; +; This file contains a 'Sample Driver' and is licensed as such +; under the terms of your license agreement with Intel or your +; vendor. This file may be modified by the user, subject to +; the additional terms of the license agreement +; +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR> +; This software and associated documentation (if any) is furnished +; under a license and may only be used or copied in accordance +; with the terms of the license. Except as permitted by such +; license, no part of this software or documentation may be +; reproduced, stored in a retrieval system, or transmitted in any +; form or by any means without the express written consent of +; Intel Corporation. + +; +; Module Name: +; +; ResetVec.asm +; +; Abstract: +; +; Reset Vector Data structure +; This structure is located at 0xFFFFFFC0 +; +;------------------------------------------------------------------------------ + + .model tiny + .686p + .stack 0h + .code + +_TEXT_REALMODE SEGMENT PARA PUBLIC USE16 'CODE' + ASSUME CS:_TEXT_REALMODE, DS:_TEXT_REALMODE + + ORG 0h +; +; FIT table pointer for LT-SX. +; +FitTablePointer DD 0eeeeeeeeh, 0eeeeeeeeh + + ORG 10h +; +; This is located at 0xFFFFFFD0h +; + mov di, "AP" + jmp ApStartup + + ORG 20h +; +; Pointer to the entry point of the PEI core +; It is located at 0xFFFFFFE0, and is fixed up by some build tool +; So if the value 8..1 appears in the final FD image, tool failure occurs. +; +PeiCoreEntryPoint DD 87654321h + +; +; This is the handler for all kinds of exceptions. Since it's for debugging +; purpose only, nothing except a deadloop would be done here. Developers could +; analyze the cause of the exception if a debugger had been attached. +; +InterruptHandler PROC + jmp $ + iret +InterruptHandler ENDP + + ORG 30h +; +; For IA32, the reset vector must be at 0xFFFFFFF0, i.e., 4G-16 byte +; Execution starts here upon power-on/platform-reset. +; +ResetHandler: + nop + nop +ApStartup: + ; + ; Jmp Rel16 instruction + ; Use machine code directly in case of the assembler optimization + ; SEC entry point relatvie address will be fixed up by some build tool. + ; + + DB 0e9h + DW -3 + + + ORG 38h +; +; Ap reset vector segment address is at 0xFFFFFFF8 +; This will be fixed up by some build tool, +; so if the value 1..8 appears in the final FD image, +; tool failure occurs +; +ApSegAddress dd 12345678h + + ORG 3ch +; +; BFV Base is at 0xFFFFFFFC +; This will be fixed up by some build tool, +; so if the value 1..8 appears in the final FD image, +; tool failure occurs. +; +BfvBase DD 12345678h + +_TEXT_REALMODE ENDS + + END diff --git a/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/ResetVec.raw b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/ResetVec.raw Binary files differnew file mode 100644 index 0000000..ca9dd3c --- /dev/null +++ b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/ResetVec.raw diff --git a/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/SecCore.inc b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/SecCore.inc new file mode 100644 index 0000000..0129cc9 --- /dev/null +++ b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/SecCore.inc @@ -0,0 +1,56 @@ +;@file +; SecCore constants and macros +; +;@copyright +; Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved +; This software and associated documentation (if any) is furnished +; under a license and may only be used or copied in accordance +; with the terms of the license. Except as permitted by such +; license, no part of this software or documentation may be +; reproduced, stored in a retrieval system, or transmitted in any +; form or by any means without the express written consent of +; Intel Corporation. +; +; This file contains a 'Sample Driver' and is licensed as such +; under the terms of your license agreement with Intel or your +; vendor. This file may be modified by the user, subject to +; the additional terms of the license agreement +; + +; +; Set to 1 to enable debug +; +NO_EVICTION_MODE_DEBUG EQU 1 + +STATUS_CODE MACRO status +IF NO_EVICTION_MODE_DEBUG + mov al, status + out 080h, al +ENDIF +ENDM + +FVHEADER_LEN_OFF EQU 30h +FFSHEADER_LEN EQU 18h + +IMAGE_BASE_ADDRESS EQU 0FFFF0000h + +; +; Set to 1 to enable debug support for "Deterministic BSP selection" +; +AP_ENTRY_DELAY EQU 10h +AP_EXECUTION_DELAY EQU 1000h + +; +; Define the segment used for AP start-up +; It should be on the top of the recovery FV +; Seg = 0100h - (BlockNumber of Recovery FV) +; Here 0FCh = 0100h - 04h +; +AP_SEG EQU 0FFh + +; +; Commands defined in the AP SIPI code +; +AP_SIPI_COLLECT_MAX_RATIO EQU 001h +AP_SIPI_PROGRAM_MAX_RATIO EQU 002h +AP_SIPI_SWITCH_BSP EQU 003h diff --git a/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/SecFlat32.inc b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/SecFlat32.inc new file mode 100644 index 0000000..7b9dea4 --- /dev/null +++ b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/SecFlat32.inc @@ -0,0 +1,1024 @@ +; +; This file contains a 'Sample Driver' and is licensed as such +; under the terms of your license agreement with Intel or your +; vendor. This file may be modified by the user, subject to +; the additional terms of the license agreement +; +;------------------------------------------------------------------------------ +; +; Copyright (c) 1999 - 2012, Intel Corporation. All rights reserved.<BR> +; This software and associated documentation (if any) is furnished +; under a license and may only be used or copied in accordance +; with the terms of the license. Except as permitted by such +; license, no part of this software or documentation may be +; reproduced, stored in a retrieval system, or transmitted in any +; form or by any means without the express written consent of +; Intel Corporation. +; +; Module Name: +; +; SecFlat32.inc +; +; Abstract: +; +; This is the code that goes from real-mode to protected mode. +; It consumes the reset vector. +; +;------------------------------------------------------------------------------ + +CALL_MMX macro RoutineLabel + + local ReturnAddress + mov esi, offset ReturnAddress + movd mm7, esi ; save ReturnAddress into MM7 + jmp RoutineLabel +ReturnAddress: + +endm + +RET_ESI macro + + movd esi, mm7 ; restore ESP from MM7 + jmp esi + +endm + +CALL_EBP macro RoutineLabel + + local ReturnAddress + mov ebp, offset ReturnAddress + jmp RoutineLabel +ReturnAddress: + +endm + +RET_EBP macro + + jmp ebp ; restore ESP from EBP + +endm + +align 4 +ProtectedModeSECStart PROC NEAR PUBLIC + STATUS_CODE (02h) + CALL_MMX EnableAccessCSR + +;(AMI_CHG+)> + STATUS_CODE (07h) + CALL_MMX VeryEarlyMicrocodeUpdate +;<(AMI_CHG+) + + CALL_MMX DetectNumOfCPUSocket + + STATUS_CODE (03h) +;(AMI_CHG+)> + ;-Things in PlatformInitialization are ready done in chipset part + ;-CALL_MMX PlatformInitialization +;<(AMI_CHG+) + STATUS_CODE (09h) + CALL_MMX InitializeNEM + + STATUS_CODE (0Bh) + jmp CallPeiCoreEntryPoint + +ProtectedModeSECStart ENDP + +EnableAccessCSR PROC NEAR PRIVATE + ; + ; get Bus number from CPUID[1] EBX[31:24] + ; + + mov eax, 0Bh + mov ecx, 1 + cpuid + mov esi, eax + + mov eax, 1 ; bus 0 + cpuid + bswap ebx + movzx eax, bl + movzx ebx, bl + shl eax, BSPApicIDSaveStart ; Save current BSP APIC ID in MM1[31:24] + mov cx, si + shr bl, cl ; get Bus number in BL + or eax, ebx + movd mm1, eax ; save Bus number MM1[7:0] + + ; + ; Enable MM PCI-E Config Space + ; --cr-- use register symbol name; should upper 32 bit be cleared + ; + mov eax, 080000060h ; MCHBAR + mov dx, 0CF8h + out dx, eax + mov dx, 0CFCh + mov eax, MMCFG_LENGTH_BIT_SETTING + out dx, eax + in eax, dx + or eax, MMCFG_BASE OR ENABLE + out dx, eax + + ; Clear reset flag + movd eax, mm1 + and eax, NOT BIT18+BIT19 + movd mm1, eax + RET_ESI + +EnableAccessCSR ENDP + +; STATUS_CODE (03h) +;PlatformInitialization PROC NEAR PRIVATE +; +; ; +; ; Program PCI Express base address +; ; +; +; mov eax, 80000060h ; 0:0:0:60 +; mov dx, 0CF8h +; out dx, eax +; mov dx, 0CFCh +; ;using Pcd instead +; ;mov eax, 0e0000000h OR 00h OR 1 +;; mov eax, DWORD PTR PcdGet64 (PcdPciExpressBaseAddress) +; mov eax, DWORD PTR PCIEXPRESS_BASE_ADDRESS +; or eax, (PCIEX_LENGTH_BIT_SETTING OR 1) +; out dx, eax +; +; ; +; ; Enable Mch Bar +; ; +; mov esi, MCHBAR_REG +; mov eax, (MCH_BASE_ADDRESS + 1) +; mov Dword Ptr [esi], eax +; +; ; +; ; Enable RCRB in PCH. +; ; +; mov esi, PCH_LPC_RCRB_PCI_ADDR +; mov eax, PCH_RCRB_BASE + 1 +; mov Dword Ptr [esi], eax +; +; ; +; ; Configure GPIO to be able to initiate LVL change for GPIO48 for S3 resume time calculation. +; ; +; ; Enable GPIO BASE I/O registers +; ; +; mov eax, PCI_LPC_BASE + 48h +; mov dx, 0CF8h +; out dx, eax +; mov eax, GPIO_BASE_ADDRESS +; add dx, 4 +; out dx, eax +; +; mov eax, PCI_LPC_BASE + 4Ch +; mov dx, 0CF8h +; out dx, eax +; add dx, 4 +; in al, dx +; or al, BIT4 ; GPIOBASE Enable +; out dx, al +; +; ;GPIO_USE_SEL2 Register -> 1 = GPIO 0 = Native +; mov dx, GPIO_BASE_ADDRESS + R_GPIO_USE_SEL2 +; in eax, dx +; or eax, 010000h ;Enable GPIO48 +; out dx, eax +; +; ;GP_IO_SEL2 Register -> 1 = Input 0 = Output (if Native Mode don't care) +; mov dx, GPIO_BASE_ADDRESS + R_GPIO_IO_SEL2 +; in eax, dx +; and eax, 0FFFEFFFFh ;Configure GPIO48 as Output +; out dx, eax +; +; mov dx, GPIO_BASE_ADDRESS + R_GPIO_LVL2 +; in eax, dx +; or eax, 010000h ;Configure GPIO48 as High +; out dx, eax +; +; ; +; ; Program and Enable ACPI PM Base. +; ; +; mov esi, PCH_LPC_PMBASE_PCI_ADDR +; mov eax, PCH_ACPI_BASE_ADDRESS + 1 +; mov Dword Ptr [esi], eax +; mov esi, PCH_LPC_ACPICNTL_PCI_ADDR +; or Dword Ptr [esi], 00000080h +; +; ; +; ; PCH BIOS Spec Rev 0.5.0 Section 12.9 +; ; Additional Programming Requirements for USB Support +; ; Step 2.b +; ; Clear RCBA + 3598h [0] to 0b +; ; +; mov esi, PCH_RCRB_BASE + 3598h +; mov eax, 0 +; mov Dword Ptr [esi], eax +; +; ; +; ; Enable HPET decode in PCH. +; ; +; mov esi, PCH_RCRB_BASE + PCH_RCRB_HPET +; mov eax, PCH_RCRB_HPET_DECODE +; mov Dword Ptr [esi], eax +; mov eax, Dword ptr [esi] +; xor eax, eax +; mov esi, HPET_COMP_1 +; mov Dword Ptr [esi], eax +; mov esi, HPET_COMP_2 +; mov Dword ptr [esi], eax +; +; ; +; ; Enable the upper 128-byte bank of RTC RAM. +; ; +; mov esi, PCH_RCRB_BASE + PCH_RCRB_RTC_CONF +; mov eax, Dword Ptr [esi] +; or eax, PCH_RCRB_RTC_CONF_UCMOS_EN +; mov Dword Ptr [esi], eax +; +; ; +; ; Choose Port80 Route +; ; +; mov esi, PCH_RCRB_BASE + PCH_RCRB_GCS +; mov ebx, Dword Ptr [esi] +; or bl, BIT5 +; +; ; +; ; check SETUP option - PchPort80Route +; ; 0 = LPC {Default]; 1 = PCI +; ; +;; mov al, CMOS_PCH_PORT80_OFFSET ; CMOS Offset = 17h +;; mov dx, RTC_UPPER_INDEX +;; out dx, al +;; inc dx +;; in al, dx +;; test al, BIT0 +;; jnz @F +; and bl, NOT (BIT2) ; Port80h to LPC +;;@@: +; mov Dword Ptr [esi], ebx +; +; ; +; ; Halt TCO Timer +; ; +; mov dx, 0468h +; in ax, dx +; or ax, BIT11 +; out dx, ax +; +; ; +; ; Clear the Second TO status bit +; ; +; mov dx, 0466h +; in ax, dx +; or ax, BIT1 +; out dx, ax +; +; RET_ESI +; +;PlatformInitialization ENDP + +; STATUS_CODE (03h) +DetectNumOfCPUSocket PROC NEAR PRIVATE + + ; only one socket + movd eax, mm1 ; get MM1 value into EAX + mov ah, 01 + movd mm1, eax ; save CPU pkg count into MM1[15:8] + + RET_ESI + +DetectNumOfCPUSocket ENDP + +; STATUS_CODE (07h) +VeryEarlyMicrocodeUpdate PROC NEAR PRIVATE +; (AMI_CHG+)> + public FindMicrocodeEnd + mov ecx,08bh + rdmsr + or dx,dx + jnz uc_exit + jmp FindMicrocode ;return to MicroCodeUpdateEnd +FindMicrocodeEnd:: + or eax, eax + jz uc_exit ;No microcode found: + + ;Update microcode + mov ecx, 79h + xor edx, edx + add eax, 48 ;eax = Update data + wrmsr ;Update microcode +uc_exit: + RET_ESI + +;-IF EARLY_MICROCODE_SUPPORT +;- mov ecx, IA32_BIOS_SIGN_ID +;- rdmsr ; CPU PatchID -> EDX +;- cmp edx, 0 ; If microcode has been updated +;- jnz luExit ; Skip if patch already loaded +;- +;- mov ecx, IA32_PLATFORM_ID ; To get Platform ID. +;- rdmsr +;- shr edx, 18 ; EDX[0-2] = Platform ID. +;- and dx, 07h ; DX = Platform ID. +;- mov si, dx ; Save Platform ID in FS. +;- mov eax, 01h ; To get CPU signature. +;- cpuid ; EAX = CPU signature. +;- mov cx, si ; CX = Platform ID +;- xor edx, edx +;- bts dx, cx ; EDX = Platform ID bit. +;- +; mov esi, PcdGet32 (PcdFlashMicrocodeFvBase) +;- mov esi, MICROCODE_FV_BASE_ADDRESS +;- +;- mov ebx, esi +;- mov bx, FVHEADER_LEN_OFF +;- movzx ebx, WORD PTR [ebx] +;- add esi, ebx +;- add si, FFSHEADER_LEN ; add FFS header +;- +;- mov edi, PcdGet32 (PcdFlashMicrocodeFvBase) +;- mov ebx, PcdGet32 (PcdFlashMicrocodeFvSize) +;- mov edi, MICROCODE_FV_BASE_ADDRESS +;- mov ebx, MICROCODE_FV_SIZE +;- add edi, ebx ;End addr of uCodes. +;- +;- ; EAX = CPU signature. +;- ; EDX = Platform ID bit. +;- ; ESI = Abs addr of contiguous uCode blocks. +;- ; EDI = Abs addr of contiguous uCode blocks end. +;- +;-luCheckPatch: +;- cmp (UpdateHeaderStruc PTR ds:[esi]).dProcessorSignature, eax;Sig matched? +;- jnz luCheckUnprogrammed ; No. +;- test (UpdateHeaderStruc PTR ds:[esi]).dProcessorFlags, edx;Platform matched? +;- jnz luFoundMatch ; Yes. +;- +;-luCheckUnprogrammed: +;- mov ebx, (UpdateHeaderStruc PTR ds:[esi]).dDataSize +;- cmp ebx, 0FFFFFFFFh +;- je luUnprogrammed +;- cmp (UpdateHeaderStruc PTR ds:[esi]).dLoaderRevision, 1 +;- je luCheckExtdHdrs +;- +;-luUnprogrammed: +;- mov ebx, 1024 ; Unprogrammed space, 1KB checks +;- jmp luPoinToNextBlock ; for backword compatibility. +;- +;-luCheckExtdHdrs: +;- add ebx, SIZEOF(UpdateHeaderStruc) +;- cmp ebx, (UpdateHeaderStruc PTR ds:[esi]).dTotalSize +;- jae luTryNextPatch ; No extd hdrs. +;- +;- mov ecx, DWORD PTR ds:[esi + ebx] +;- jcxz luTryNextPatch ; No extd hdrs. (OK to use CX instead of ECX). +;- add ebx, 20 ; Point to the first Extd Sig. +;-luNextSig: +;- cmp eax, DWORD PTR ds:[esi + ebx] ;Sig matched? +;- jne lu_00 +;- test edx, DWORD PTR ds:[esi + ebx + 4] ;Platform matched? +;- jnz luFoundMatch +;-lu_00: +;- add ebx, 12 +;- loop luNextSig +;- +;-luTryNextPatch: +;- mov ebx, (UpdateHeaderStruc PTR ds:[esi]).dTotalSize +;- or ebx, ebx +;- jnz luPoinToNextBlock ; Variable size uCode format. +;- mov ebx, BLOCK_LENGTH_BYTES ; Fixed size uCode format. + +; +; Add alignment check - begin +; +;- test ebx, 0400h +;- jz @F +;- add ebx, 0400h +;-@@: +; +; Add alignment check - end +; + +;-luPoinToNextBlock: +;- add esi, ebx +;- cmp esi, edi +;- jb luCheckPatch ; Check with all patches. +;- +;- ; Check possible multiple patch +;- movd eax, mm3 +;- movd esi, mm4 +;- or eax, eax +;- jnz luLoadPatch +;- jmp luExit ; No matching patch found. +;- +;-luFoundMatch: +;-; MM3 = Patch Revision +;-; MM4 = Patch Pointer +;- movd ebx, mm3 +;- cmp (UpdateHeaderStruc PTR ds:[esi]).dUpdateRevision, ebx +;- jb luTryNextPatch +;- +;- mov ebx, (UpdateHeaderStruc PTR ds:[esi]).dUpdateRevision +;- +;-luStoreRevPtr: +;- movd mm3, ebx ; save Patch Revision +;- movd mm4, esi ; save Patch Pointer +;- jmp luTryNextPatch +;- +;-luLoadPatch: +;- mov ecx, IA32_BIOS_UPDT_TRIG +;- mov eax, esi ; EAX - Abs addr of uCode patch. +;- add eax, SIZEOF(UpdateHeaderStruc) ; EAX - Abs addr of uCode data. +;- xor edx, edx ; EDX:EAX - Abs addr of uCode data. +;- wrmsr ; Trigger uCode load. +;- +;-luExit: +;-ENDIF +;- +;- RET_EBP +;<(AMI_CHG+) +VeryEarlyMicrocodeUpdate ENDP +; STATUS_CODE (09h) +;************************************************************ +; Description: +; +; This function initializes the Cache for Data, Stack, and Code +; as specified in the BIOS Writer's Guide. +;************************************************************ +InitializeNEM PROC NEAR PRIVATE +IFDEF ANC_SUPPORT_FLAG + ; + ; Detect AnC Boot + ; + mov ecx, MSR_ANC_SACM_INFO ; + rdmsr + and eax, 01h + jnz AncNemSetup +ENDIF + + ; + ; Enable cache for use as stack and for caching code + ; The algorithm is specified in the processor BIOS writer's guide + ; + + ; + ; Ensure that the system is in flat 32 bit protected mode. + ; + ; Platform Specific - configured earlier + ; + ; Ensure that only one logical processor in the system is the BSP. + ; (Required step for clustered systems). + ; + ; Platform Specific - configured earlier + + ; Ensure all APs are in the Wait for SIPI state. + ; This includes all other logical processors in the same physical processor + ; as the BSP and all logical processors in other physical processors. + ; If any APs are awake, the BIOS must put them back into the Wait for + ; SIPI state by issuing a broadcast INIT IPI to all excluding self. + ; + mov edi, APIC_ICR_LO ; 0FEE00300h - Send INIT IPI to all excluding self + mov eax, ORAllButSelf + ORSelfINIT ; 0000C4500h + mov [edi], eax + +@@: + mov eax, [edi] + bt eax, 12 ; Check if send is in progress + jc @B ; Loop until idle + + ; + ; Load microcode update into BSP. + ; + ; Ensure that all variable-range MTRR valid flags are clear and + ; IA32_MTRR_DEF_TYPE MSR E flag is clear. Note: This is the default state + ; after hardware reset. + ; + ; Platform Specific - MTRR are usually in default state. + ; + + ; + ; Initialize all fixed-range and variable-range MTRR register fields to 0. + ; + mov ecx, IA32_MTRR_CAP ; get variable MTRR support + rdmsr + movzx ebx, al ; EBX = number of variable MTRR pairs + shl ebx, 2 ; *4 for Base/Mask pair and WORD size + add ebx, MtrrCountFixed * 2 ; EBX = size of Fixed and Variable MTRRs + + xor eax, eax ; Clear the low dword to write + xor edx, edx ; Clear the high dword to write + ;;;mov ebx, MtrrCount * 2 ; ebx <- sizeof MtrrInitTable +InitMtrrLoop: + add ebx, -2 + movzx ecx, WORD PTR cs:MtrrInitTable[ebx] ; ecx <- address of mtrr to zero + wrmsr + jnz InitMtrrLoop ; loop through the whole table + + ; + ; Configure the default memory type to un-cacheable (UC) in the + ; IA32_MTRR_DEF_TYPE MSR. + ; + mov ecx, MTRR_DEF_TYPE ; Load the MTRR default type index + rdmsr + and eax, NOT (00000CFFh) ; Clear the enable bits and def type UC. + wrmsr + + ; Configure MTRR_PHYS_MASK_HIGH for proper addressing above 4GB + ; based on the physical address size supported for this processor + ; This is based on read from CPUID EAX = 080000008h, EAX bits [7:0] + ; + ; Examples: + ; MTRR_PHYS_MASK_HIGH = 00000000Fh For 36 bit addressing + ; MTRR_PHYS_MASK_HIGH = 0000000FFh For 40 bit addressing + ; + mov eax, 80000008h ; Address sizes leaf + cpuid + sub al, 32 + movzx eax, al + xor esi, esi + bts esi, eax + dec esi ; esi <- MTRR_PHYS_MASK_HIGH + + ; + ; Configure the DataStack region as write-back (WB) cacheable memory type + ; using the variable range MTRRs. + ; + + ; + ; Set the base address of the DataStack cache range + ; +; mov eax, PcdGet32 (PcdTemporaryRamBase) + mov eax, TEMPORARY_RAM_BASE_ADDRESS + or eax, MTRR_MEMORY_TYPE_WB + ; Load the write-back cache value + xor edx, edx ; clear upper dword + mov ecx, MTRR_PHYS_BASE_0 ; Load the MTRR index + wrmsr ; the value in MTRR_PHYS_BASE_0 + + ; + ; Set the mask for the DataStack cache range + ; Compute MTRR mask value: Mask = NOT (Size - 1) + ; +; mov eax, PcdGet32 (PcdTemporaryRamSize) + mov eax, TEMPORARY_RAM_SIZE + dec eax + not eax + or eax, MTRR_PHYS_MASK_VALID + ; turn on the Valid flag + mov edx, esi ; edx <- MTRR_PHYS_MASK_HIGH + mov ecx, MTRR_PHYS_MASK_0 ; For proper addressing above 4GB + wrmsr ; the value in MTRR_PHYS_BASE_0 + + ; + ; Configure the BIOS code region as write-protected (WP) cacheable + ; memory type using a single variable range MTRR. + ; + ; Platform Specific - ensure region to cache meets MTRR requirements for + ; size and alignment. + ; + + ; + ; Set the base address of the CodeRegion cache range part 1 + ; + mov eax, CODE_REGION_BASE_ADDRESS_PART1 OR MTRR_MEMORY_TYPE_WP + ; Load the write-protected cache value + xor edx, edx ; clear upper dword + mov ecx, MTRR_PHYS_BASE_1 ; Load the MTRR index + wrmsr ; the value in MTRR_PHYS_BASE_1 + + ; + ; Set the mask for the CodeRegion cache range part 1 + ; + mov eax, CODE_REGION_SIZE_MASK_PART1 OR MTRR_PHYS_MASK_VALID + ; turn on the Valid flag + mov edx, esi ; edx <- MTRR_PHYS_MASK_HIGH + mov ecx, MTRR_PHYS_MASK_1 ; Load the MTRR index + wrmsr ; the value in MTRR_PHYS_BASE_1 + +;(AMI_CHG)> +IF MKF_CODE_CACHE_PART2_BASE + ; + ; Set the base address of the CodeRegion cache range part 2 + ; + mov eax, CODE_REGION_BASE_ADDRESS_PART2 OR MTRR_MEMORY_TYPE_WP + ; Load the write-protected cache value + xor edx, edx ; clear upper dword +;- mov ecx, MTRR_PHYS_BASE_2 ; Load the MTRR index + inc ecx + wrmsr ; the value in MTRR_PHYS_BASE_2 + + ; + ; Set the mask for the CodeRegion cache range part 2 + ; + mov eax, CODE_REGION_SIZE_MASK_PART2 OR MTRR_PHYS_MASK_VALID + ; turn on the Valid flag + mov edx, esi ; edx <- MTRR_PHYS_MASK_HIGH +;- mov ecx, MTRR_PHYS_MASK_2 ; Load the MTRR index + inc ecx + wrmsr ; the value in MTRR_PHYS_BASE_1 +ENDIF + +IF MKF_WDB_REGION_BASE_ADDRESS + ; + ; Set the base address of the WDB range + ; + mov eax, WDB_REGION_BASE_ADDRESS OR MTRR_MEMORY_TYPE_WC + ; Load the write-combined cache value + xor edx, edx ; clear upper dword +;- mov ecx, MTRR_PHYS_BASE_3 ; Load the MTRR index + inc ecx + wrmsr ; the value in MTRR_PHYS_BASE_2 + + ; + ; Set the mask for the WDB range + ; + mov eax, WDB_REGION_SIZE_MASK OR MTRR_PHYS_MASK_VALID + ; turn on the Valid flag + mov edx, esi ; edx <- MTRR_PHYS_MASK_HIGH +;- mov ecx, MTRR_PHYS_MASK_3 ; Load the MTRR index + inc ecx + wrmsr ; the value in MTRR_PHYS_BASE_1 +ENDIF +;<(AMI_CHG) + + ; + ; Enable the MTRRs by setting the IA32_MTRR_DEF_TYPE MSR E flag. + ; + mov ecx, MTRR_DEF_TYPE ; Load the MTRR default type index + rdmsr + or eax, MTRR_DEF_TYPE_E ; Enable variable range MTRRs + wrmsr + + ; + ; Enable the logical processor's (BSP) cache: execute INVD and set + ; CR0.CD = 0, CR0.NW = 0. + ; + mov eax, cr0 + and eax, NOT (CR0_CACHE_DISABLE + CR0_NO_WRITE) + invd + mov cr0, eax + ; + ; Enable No-Eviction Mode Setup State by setting + ; NO_EVICT_MODE MSR 2E0h bit [0] = '1'. + ; + mov ecx, NO_EVICT_MODE + rdmsr + or eax, 1 + wrmsr + + ; + ; One location in each 64-byte cache line of the DataStack region + ; must be written to set all cache values to the modified state. + ; +; mov edi, PcdGet32 (PcdTemporaryRamBase) +; mov ecx, PcdGet32 (PcdTemporaryRamSize) + mov edi, TEMPORARY_RAM_BASE_ADDRESS + mov ecx, TEMPORARY_RAM_SIZE + shr ecx, 6 + mov eax, CACHE_INIT_VALUE +@@: + mov [edi], eax + sfence + add edi, 64 + loopd @b + + ; + ; Enable No-Eviction Mode Run State by setting + ; NO_EVICT_MODE MSR 2E0h bit [1] = '1'. + ; + mov ecx, NO_EVICT_MODE + rdmsr + or eax, 2 + wrmsr + +IFDEF ANC_SUPPORT_FLAG + jmp FinishedCacheConfig + + ; + ; Jump to here when AnC boot and NEM is initialized by AnC ACM + ; +AncNemSetup: + ; + ; Finished with cache configuration + ; + ; Configure MTRR_PHYS_MASK_HIGH for proper addressing above 4GB + ; based on the physical address size supported for this processor + ; This is based on read from CPUID EAX = 080000008h, EAX bits [7:0] + ; + ; Examples: + ; MTRR_PHYS_MASK_HIGH = 00000000Fh For 36 bit addressing + ; MTRR_PHYS_MASK_HIGH = 0000000FFh For 40 bit addressing + ; + mov eax, 80000008h ; Address sizes leaf + cpuid + sub al, 32 + movzx eax, al + xor esi, esi + bts esi, eax + dec esi ; esi <- MTRR_PHYS_MASK_HIGH + + ; + ; Configure the DataStack region as write-back (WB) cacheable memory type + ; using the variable range MTRRs. + ; + ; + ; Find available MTRR + ; + CALL_EBP FindFreeMtrr + + ; + ; Set the base address of the DataStack cache range + ; +; mov eax, PcdGet32 (PcdTemporaryRamBase) + mov eax, TEMPORARY_RAM_BASE_ADDRESS + or eax, MTRR_MEMORY_TYPE_WB + ; Load the write-back cache value + xor edx, edx ; clear upper dword + wrmsr ; the value in MTRR_PHYS_BASE_0 + + ; + ; Set the mask for the DataStack cache range + ; Compute MTRR mask value: Mask = NOT (Size - 1) + ; +; mov eax, PcdGet32 (PcdTemporaryRamSize) + mov eax, TEMPORARY_RAM_SIZE + dec eax + not eax + or eax, MTRR_PHYS_MASK_VALID + ; turn on the Valid flag + mov edx, esi ; edx <- MTRR_PHYS_MASK_HIGH + inc ecx + wrmsr ; the value in MTRR_PHYS_BASE_0 + + ; + ; Program the variable MTRR's MASK register for WDB + ; (Write Data Buffer, used in MRC, must be WC type) + ; + + ; + ; Find available MTRR + ; + CALL_EBP FindFreeMtrr + +FoundAvailableMtrr: + ; + ; Program the variable MTRR's BASE register for WDB + ; + xor edx, edx + mov eax, WDB_REGION_BASE_ADDRESS OR MTRR_MEMORY_TYPE_WC + wrmsr + + inc ecx + mov edx, esi ; edx <- MTRR_PHYS_MASK_HIGH + mov eax, WDB_REGION_SIZE_MASK OR MTRR_PHYS_MASK_VALID ; turn on the Valid flag + wrmsr + + ; + ; One location in each 64-byte cache line of the DataStack region + ; must be written to set all cache values to the modified state. + ; +; mov edi, PcdGet32 (PcdTemporaryRamBase) +; mov ecx, PcdGet32 (PcdTemporaryRamSize) + mov edi, TEMPORARY_RAM_BASE_ADDRESS + mov ecx, TEMPORARY_RAM_SIZE + shr ecx, 6 + mov eax, CACHE_INIT_VALUE +@@: + mov [edi], eax + sfence + add edi, 64 + loopd @b +ENDIF + + ; + ; Finished with cache configuration + ; +FinishedCacheConfig: + + ; + ; Optionally Test the Region... + ; + + ; + ; Test area by writing and reading + ; + cld +; mov edi, PcdGet32 (PcdTemporaryRamBase) +; mov ecx, PcdGet32 (PcdTemporaryRamSize) + mov edi, TEMPORARY_RAM_BASE_ADDRESS + mov ecx, TEMPORARY_RAM_SIZE + shr ecx, 2 + mov eax, CACHE_TEST_VALUE +TestDataStackArea: + stosd + cmp eax, DWORD PTR [edi-4] + jnz DataStackTestFail + loop TestDataStackArea + jmp DataStackTestPass + + ; + ; Cache test failed + ; +DataStackTestFail: + STATUS_CODE (0D0h) + jmp $ + + ; + ; Configuration test failed + ; +ConfigurationTestFailed: + STATUS_CODE (0D1h) + jmp $ + +DataStackTestPass: + + ; + ; At this point you may continue normal execution. Typically this would include + ; reserving stack, initializing the stack pointer, etc. + ; + + ; + ; After memory initialization is complete, please follow the algorithm in the BIOS + ; Writer's Guide to properly transition to a normal system configuration. + ; The algorithm covers the required sequence to properly exit this mode. + ; + + RET_ESI + +InitializeNEM ENDP + +; STATUS_CODE (09h) +;-EstablishStack PROC NEAR PRIVATE +;- +;- ; +;- ; Enable STACK +;- ; +;- RET_ESI +;- +;-EstablishStack ENDP +;- +;-FindFreeMtrr PROC NEAR PRIVATE +;- mov ecx, MTRR_PHYS_MASK_0 +;- +;-@@: +;- rdmsr +;- test eax, 800h +;- jz FoundFreeMtrr +;- add ecx, 2 +;- cmp ecx, MTRR_PHYS_MASK_9 +;- jbe @b +;- ; +;- ; No available MTRR, halt system +;- ; +;- jmp $ +;- +;-FoundFreeMtrr: +;- dec ecx +;- +;- RET_EBP +;- +;-FindFreeMtrr ENDP +;- +;-; STATUS_CODE (0Bh) +;-CallPeiCoreEntryPoint PROC NEAR PRIVATE +;- ; +;- ; Set stack top pointer +;- ; +;-; mov esp, PcdGet32 (PcdTemporaryRamBase) +;-; add esp, PcdGet32 (PcdTemporaryRamSize) +;- mov esp, TEMPORARY_RAM_BASE_ADDRESS +;- add esp, TEMPORARY_RAM_SIZE +;- +;- ; +;- ; Push CPU count to stack first, then AP's (if there is one) +;- ; BIST status, and then BSP's +;- ; +;- +;- ; +;- ; Here work around for BIST +;- ; +;- ; Get number of BSPs +;- movd ecx, mm1 +;- movzx ecx, ch +;- +;- ; Save number of BSPs +;- push ecx +;- +;-GetSBSPBist: +;- ; Save SBSP BIST +;- movd eax, mm0 +;- push eax +;- +;- ; Save SBSP APIC ID +;- movd eax, mm1 +;- shr eax, BSPApicIDSaveStart ; Resume APIC ID +;- push eax +;- +;- ; Save Time-Stamp Counter +;- movd eax, mm5 +;- push eax +;- +;- movd eax, mm6 +;- push eax +;- +;-TransferToSecStartup: +;- +;- +;- +;- ; Switch to "C" code +;- STATUS_CODE (0Ch) +;- ; +;- ; Pass entry point of the PEI core +;- ; +;- mov edi, PEI_CORE_ENTRY_BASE ; 0FFFFFFE0h +;- push DWORD PTR ds:[edi] +;- +;- ; +;- ; Pass BFV into the PEI Core +;- ; +;- mov edi, FV_MAIN_BASE ; 0FFFFFFFCh +;- push DWORD PTR ds:[edi] +;- +;- ; ECPoverride: SecStartup entry point needs 4 parameters +;-; push PcdGet32 (PcdTemporaryRamBase) +;- push TEMPORARY_RAM_BASE_ADDRESS +;- +;- ; +;- ; Pass stack size into the PEI Core +;- ; +;-; push PcdGet32 (PcdTemporaryRamSize) +;- push TEMPORARY_RAM_SIZE +;- +;- ; +;- ; Pass Control into the PEI Core +;- ; +;- call SecStartup +;-CallPeiCoreEntryPoint ENDP +;- +;-StartUpAp PROC NEAR +;- +;- mov esi, HPET_COMP_2 +;- lock inc byte ptr [esi] +;- +;- DISABLE_CACHE +;-; +;-; Halt the AP and wait for the next SIPI +;-; +;-Ap_Halt: +;- cli +;-@@: +;- hlt +;- jmp @B +;- ret +;-StartUpAp ENDP +;- +;- +;-CheckValidCMOS PROC NEAR PRIVATE +;- ; +;- ; Check CMOS Status +;- ; +;- mov esi, PCH_LPC_GEN_PMCON_3_ADDR +;- mov eax, es:[esi] +;- +;- ; check PWR_FLR and RTC_PWR_STS status +;- and eax, BIT2 + BIT1 +;- +;- RET_EBP +;-CheckValidCMOS ENDP + +MtrrInitTable LABEL BYTE + DW MTRR_DEF_TYPE + DW MTRR_FIX_64K_00000 + DW MTRR_FIX_16K_80000 + DW MTRR_FIX_16K_A0000 + DW MTRR_FIX_4K_C0000 + DW MTRR_FIX_4K_C8000 + DW MTRR_FIX_4K_D0000 + DW MTRR_FIX_4K_D8000 + DW MTRR_FIX_4K_E0000 + DW MTRR_FIX_4K_E8000 + DW MTRR_FIX_4K_F0000 + DW MTRR_FIX_4K_F8000 + +MtrrCountFixed EQU (($ - MtrrInitTable) / 2) + + DW MTRR_PHYS_BASE_0 + DW MTRR_PHYS_MASK_0 + DW MTRR_PHYS_BASE_1 + DW MTRR_PHYS_MASK_1 + DW MTRR_PHYS_BASE_2 + DW MTRR_PHYS_MASK_2 + DW MTRR_PHYS_BASE_3 + DW MTRR_PHYS_MASK_3 + DW MTRR_PHYS_BASE_4 + DW MTRR_PHYS_MASK_4 + DW MTRR_PHYS_BASE_5 + DW MTRR_PHYS_MASK_5 + DW MTRR_PHYS_BASE_6 + DW MTRR_PHYS_MASK_6 + DW MTRR_PHYS_BASE_7 + DW MTRR_PHYS_MASK_7 + DW MTRR_PHYS_BASE_8 + DW MTRR_PHYS_MASK_8 + DW MTRR_PHYS_BASE_9 + DW MTRR_PHYS_MASK_9 +MtrrCount EQU (($ - MtrrInitTable) / 2) diff --git a/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/SecStartup.c b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/SecStartup.c new file mode 100644 index 0000000..9c6f19c --- /dev/null +++ b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/SecStartup.c @@ -0,0 +1,136 @@ +/** @file + SEC Startup function invoked after SEC Ram is started. + +@copyright + Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains a 'Sample Driver' and is licensed as such + under the terms of your license agreement with Intel or your + vendor. This file may be modified by the user, subject to + the additional terms of the license agreement +**/ +#include "Tiano.h" +#include "PeiCore.h" +#include "FlashMap.h" +#include "EfiFirmwareFileSystem.h" +#include "EfiFirmwareVolumeHeader.h" + +#include EFI_PPI_DEFINITION (SecPlatformInformation) + +/// +/// Define the Microcode FV base and size +/// So as to be used by Flat32.asm +/// Here the Microcode binary is embedded in a FFS within a FV +/// So the header should be taken into count to get the raw data +/// In FV header, the EFI_FV_BLOCK_MAP_ENTRY is an array with variable size +/// If the map is changed, it has to be adjusted as well. +/// +UINT32 MicrocodeStart = FLASH_REGION_NVSTORAGE_SUBREGION_MICROCODE_BASE + + sizeof (EFI_FFS_FILE_HEADER); +UINT32 MicrocodeEnd = FLASH_REGION_NVSTORAGE_SUBREGION_MICROCODE_BASE + + FLASH_REGION_NVSTORAGE_SUBREGION_MICROCODE_SIZE; + +extern UINT32 *TopOfCar; + +EFI_STATUS +SecPlatformInformation ( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT UINT64 *StructureSize, + IN OUT SEC_PLATFORM_INFORMATION_RECORD *PlatformInformationRecord + ); + +EFI_SEC_PLATFORM_INFORMATION_PPI mSecPlatformInformationPpi = { SecPlatformInformation }; + +EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformationPpi = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiSecPlatformInformationPpiGuid, + &mSecPlatformInformationPpi +}; + +/** + Implementation of the PlatformInformation service in + EFI_SEC_PLATFORM_INFORMATION_PPI. + This function conveys state information out of the SEC phase into PEI. + + @param[in] PeiServices - Pointer to the PEI Services Table. + @param[in] StructureSize - Pointer to the variable describing size of the input buffer. + @param[in] PlatformInformationRecord - Pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD. + + @retval EFI_SUCCESS - The data was successfully returned. + @retval EFI_BUFFER_TOO_SMALL - The buffer was too small. +**/ +EFI_STATUS +EFIAPI +SecPlatformInformation ( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT UINT64 *StructureSize, + IN OUT SEC_PLATFORM_INFORMATION_RECORD *PlatformInformationRecord + ) +{ + UINT32 *BIST; + UINT32 Size; + UINT32 Count; + + /// + /// The entries of BIST information, together with the number of them, + /// reside in the bottom of stack, left untouched by normal stack operation. + /// This routine copies the BIST information to the buffer pointed by + /// PlatformInformationRecord for output. + /// + Count = *(TopOfCar - 1); + Size = Count * sizeof (UINT64); + + if ((*StructureSize) < (UINT64) Size) { + *StructureSize = Size; + return EFI_BUFFER_TOO_SMALL; + } + + *StructureSize = Size; + BIST = (UINT32 *) ((UINT32) TopOfCar - sizeof (UINT32) - Size); + + EfiCommonLibCopyMem (PlatformInformationRecord, BIST, Size); + + return EFI_SUCCESS; +} + +/** + Entry point to the C language phase of SEC. After the SEC assembly + code has initialized some temporary memory and set up the stack, + the control is transferred to this function. + + @param[in] SizeOfRam - Size of the temporary memory available for use. + @param[in] BootFirmwareVolume - Base address of the Boot Firmware Volume. + @param[in] PeiCoreEntryPoint - Pointer to the entry point of the PEI core. + + @retval This function never returns +**/ +VOID +SecStartup ( + IN UINT32 SizeOfRam, + IN UINT32 BootFirmwareVolume, + IN PEI_MAIN_ENTRY_POINT PeiCoreEntryPoint + ) +{ + EFI_PEI_STARTUP_DESCRIPTOR PeiStartup; + + PeiStartup.SizeOfCacheAsRam = SizeOfRam; + PeiStartup.BootFirmwareVolume = BootFirmwareVolume; + PeiStartup.DispatchTable = &mPeiSecPlatformInformationPpi; + + /// + /// Transfer the control to the PEI core + /// + (*PeiCoreEntryPoint)(&PeiStartup); + + /// + /// Should not come here. + /// + return; +} |