summaryrefslogtreecommitdiff
path: root/ReferenceCode/Haswell/SampleCode/SecCore/Sec
diff options
context:
space:
mode:
authorraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
committerraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
commitb7c51c9cf4864df6aabb99a1ae843becd577237c (patch)
treeeebe9b0d0ca03062955223097e57da84dd618b9a /ReferenceCode/Haswell/SampleCode/SecCore/Sec
downloadzprj-master.tar.xz
init. 1AQQW051HEADmaster
Diffstat (limited to 'ReferenceCode/Haswell/SampleCode/SecCore/Sec')
-rw-r--r--ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/Chipset.inc107
-rw-r--r--ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/CpuRcSec.asm38
-rw-r--r--ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/CrcSecPpi.c233
-rw-r--r--ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/Flat32.asm1490
-rw-r--r--ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/Ia32.inc164
-rw-r--r--ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/Platform.inc196
-rw-r--r--ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/ResetVec.asm108
-rw-r--r--ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/ResetVec.rawbin0 -> 64 bytes
-rw-r--r--ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/SecCore.inc56
-rw-r--r--ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/SecFlat32.inc1024
-rw-r--r--ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/SecStartup.c136
11 files changed, 3552 insertions, 0 deletions
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
new file mode 100644
index 0000000..ca9dd3c
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/ResetVec.raw
Binary files differ
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;
+}