summaryrefslogtreecommitdiff
path: root/ReferenceCode/Haswell
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
downloadzprj-b7c51c9cf4864df6aabb99a1ae843becd577237c.tar.xz
init. 1AQQW051HEADmaster
Diffstat (limited to 'ReferenceCode/Haswell')
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/CacheData.c515
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/CacheData.h91
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/CpuFvi.c62
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxe.c1085
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxe.cif46
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxe.dxs57
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxe.h546
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxe.inf171
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxe.mak140
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxe.sdl45
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxeDbgr.c1112
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxeDbgr.h602
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxeStrings.unibin0 -> 2418 bytes
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/Exception.h92
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/Features.c1093
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/Features.h145
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/MachineCheck.c133
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/MachineCheck.h109
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/MemoryAttribute.c895
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/MemoryAttribute.h259
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/Microcode.c547
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/MpCommon.c1186
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/MpCommon.h606
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/MpService.c2194
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/MpService.h670
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/MtrrSync.c338
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/PiMpService.c957
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/PiMpService.h242
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/ProcessorData.c795
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/ProcessorData.h136
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/x64/Cpu.asm626
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/x64/CpuLib.h168
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/x64/Exception.c372
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/x64/MemoryOperation.c729
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/x64/MemoryOperationDbgr.c749
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/x64/MpCpu.c89
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/x64/MpEqu.inc51
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/x64/MpFuncs.asm618
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/x64/ProcessorDef.h57
-rw-r--r--ReferenceCode/Haswell/CpuInit/Dxe/x64/VirtualMemory.h145
-rw-r--r--ReferenceCode/Haswell/CpuInit/Pei/BootGuardInit.c111
-rw-r--r--ReferenceCode/Haswell/CpuInit/Pei/CachePeim.c1045
-rw-r--r--ReferenceCode/Haswell/CpuInit/Pei/CpuInitPei.cif20
-rw-r--r--ReferenceCode/Haswell/CpuInit/Pei/CpuInitPei.mak76
-rw-r--r--ReferenceCode/Haswell/CpuInit/Pei/CpuInitPei.sdl37
-rw-r--r--ReferenceCode/Haswell/CpuInit/Pei/CpuInitPeim.c1404
-rw-r--r--ReferenceCode/Haswell/CpuInit/Pei/CpuInitPeim.dxs42
-rw-r--r--ReferenceCode/Haswell/CpuInit/Pei/CpuInitPeim.h212
-rw-r--r--ReferenceCode/Haswell/CpuInit/Pei/CpuInitPeim.inf124
-rw-r--r--ReferenceCode/Haswell/CpuInit/Pei/CpuOcInit.c292
-rw-r--r--ReferenceCode/Haswell/CpuInit/Pei/CpuOcInit.h55
-rw-r--r--ReferenceCode/Haswell/CpuInit/Pei/Ia32/Cpu.asm77
-rw-r--r--ReferenceCode/Haswell/CpuInit/Pei/PfatInit.c191
-rw-r--r--ReferenceCode/Haswell/CpuInit/Pei/PfatInit.h42
-rw-r--r--ReferenceCode/Haswell/CpuS3/Pei/CpuAsm.asm147
-rw-r--r--ReferenceCode/Haswell/CpuS3/Pei/CpuS3Peim.c1035
-rw-r--r--ReferenceCode/Haswell/CpuS3/Pei/CpuS3Peim.cif18
-rw-r--r--ReferenceCode/Haswell/CpuS3/Pei/CpuS3Peim.dxs31
-rw-r--r--ReferenceCode/Haswell/CpuS3/Pei/CpuS3Peim.inf102
-rw-r--r--ReferenceCode/Haswell/CpuS3/Pei/CpuS3Peim.mak76
-rw-r--r--ReferenceCode/Haswell/CpuS3/Pei/CpuS3Peim.sdl37
-rw-r--r--ReferenceCode/Haswell/CpuS3/Pei/Microcode.c472
-rw-r--r--ReferenceCode/Haswell/CpuS3/Pei/MpCommon.h275
-rw-r--r--ReferenceCode/Haswell/CpuS3/Pei/MpEqu.inc51
-rw-r--r--ReferenceCode/Haswell/CpuS3/Pei/MpFuncs.asm196
-rw-r--r--ReferenceCode/Haswell/CpuS3/Pei/MtrrSync.c288
-rw-r--r--ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorInitStatus.h46
-rw-r--r--ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorLib.h62
-rw-r--r--ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.c1536
-rw-r--r--ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.cif15
-rw-r--r--ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.dxs52
-rw-r--r--ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.h477
-rw-r--r--ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.inf106
-rw-r--r--ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.mak77
-rw-r--r--ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.sdl25
-rw-r--r--ReferenceCode/Haswell/Docs/Haswell_CPU_RC_ReleaseNotes.pdfbin0 -> 221096 bytes
-rw-r--r--ReferenceCode/Haswell/Docs/Intel Haswell Processor Reference Code Specification_1.9.0.pdfbin0 -> 1266451 bytes
-rw-r--r--ReferenceCode/Haswell/Docs/RcCpuApi.chmbin0 -> 1175704 bytes
-rw-r--r--ReferenceCode/Haswell/Docs/ReleaseNotes.txt54
-rw-r--r--ReferenceCode/Haswell/Guid/CpuGuidLib.cif24
-rw-r--r--ReferenceCode/Haswell/Guid/CpuGuidLib.inf68
-rw-r--r--ReferenceCode/Haswell/Guid/CpuGuidLib.mak19
-rw-r--r--ReferenceCode/Haswell/Guid/CpuGuidLib.sdl26
-rw-r--r--ReferenceCode/Haswell/Guid/HtBistHob/HtBistHob.c24
-rw-r--r--ReferenceCode/Haswell/Guid/HtBistHob/HtBistHob.h29
-rw-r--r--ReferenceCode/Haswell/Guid/PowerMgmtAcpiTableStorage/PowerMgmtAcpiTableStorage.c40
-rw-r--r--ReferenceCode/Haswell/Guid/PowerMgmtAcpiTableStorage/PowerMgmtAcpiTableStorage.h35
-rw-r--r--ReferenceCode/Haswell/Guid/PoweronHob/PoweronHob.c24
-rw-r--r--ReferenceCode/Haswell/Guid/PoweronHob/PoweronHob.h29
-rw-r--r--ReferenceCode/Haswell/Guid/SmramCpuDataHeader/SmramCpuDataHeader.c24
-rw-r--r--ReferenceCode/Haswell/Guid/SmramCpuDataHeader/SmramCpuDataHeader.h32
-rw-r--r--ReferenceCode/Haswell/Guid/SmramCpuDataVariable/SmramCpuDataVariable.c24
-rw-r--r--ReferenceCode/Haswell/Guid/SmramCpuDataVariable/SmramCpuDataVariable.h46
-rw-r--r--ReferenceCode/Haswell/Guid/TxtInfoHob/TxtInfoHob.c33
-rw-r--r--ReferenceCode/Haswell/Guid/TxtInfoHob/TxtInfoHob.h65
-rw-r--r--ReferenceCode/Haswell/Guid/TxtOneTouch/TxtOneTouch.c33
-rw-r--r--ReferenceCode/Haswell/Guid/TxtOneTouch/TxtOneTouch.h53
-rw-r--r--ReferenceCode/Haswell/Haswell.chmbin0 -> 178384 bytes
-rw-r--r--ReferenceCode/Haswell/HaswellPkg.cif12
-rw-r--r--ReferenceCode/Haswell/HaswellPkg.sdl10
-rw-r--r--ReferenceCode/Haswell/HaswellRcPkg.cif46
-rw-r--r--ReferenceCode/Haswell/HaswellRcPkg.sdl206
-rw-r--r--ReferenceCode/Haswell/Include/CommonIncludes.h120
-rw-r--r--ReferenceCode/Haswell/Include/CpuAccess.h28
-rw-r--r--ReferenceCode/Haswell/Include/CpuBaseLib.h193
-rw-r--r--ReferenceCode/Haswell/Include/CpuDataStruct.h142
-rw-r--r--ReferenceCode/Haswell/Include/CpuPowerMgmt.dsc145
-rw-r--r--ReferenceCode/Haswell/Include/CpuRcInclude.cif27
-rw-r--r--ReferenceCode/Haswell/Include/CpuRegs.h582
-rw-r--r--ReferenceCode/Haswell/Include/IntelCpuDxe.dsc53
-rw-r--r--ReferenceCode/Haswell/Include/IntelCpuDxeLib.dsc41
-rw-r--r--ReferenceCode/Haswell/Include/IntelCpuPei.dsc35
-rw-r--r--ReferenceCode/Haswell/Include/IntelCpuPeiLib.dsc30
-rw-r--r--ReferenceCode/Haswell/Include/Library/BootGuardLibrary.h46
-rw-r--r--ReferenceCode/Haswell/Include/Library/CpuPlatformLib.h221
-rw-r--r--ReferenceCode/Haswell/Include/Library/TxtLibrary.h44
-rw-r--r--ReferenceCode/Haswell/Include/PfatDefinitions.h328
-rw-r--r--ReferenceCode/Haswell/Include/PowerMgmtDefinitions.h145
-rw-r--r--ReferenceCode/Haswell/Include/ThunkLib.h154
-rw-r--r--ReferenceCode/Haswell/Include/TisPc.h71
-rw-r--r--ReferenceCode/Haswell/Include/Txt.h160
-rw-r--r--ReferenceCode/Haswell/Include/Txt.inc442
-rw-r--r--ReferenceCode/Haswell/Library/BootGuardLib.cif11
-rw-r--r--ReferenceCode/Haswell/Library/BootGuardLib.mak20
-rw-r--r--ReferenceCode/Haswell/Library/BootGuardLib.sdl32
-rw-r--r--ReferenceCode/Haswell/Library/BootGuardLib/BootGuardLib.inf64
-rw-r--r--ReferenceCode/Haswell/Library/BootGuardLib/BootGuardLibrary.c121
-rw-r--r--ReferenceCode/Haswell/Library/CpuPlatformLib.cif12
-rw-r--r--ReferenceCode/Haswell/Library/CpuPlatformLib.mak28
-rw-r--r--ReferenceCode/Haswell/Library/CpuPlatformLib.sdl31
-rw-r--r--ReferenceCode/Haswell/Library/CpuPlatformLib/CpuPlatformLib.inf66
-rw-r--r--ReferenceCode/Haswell/Library/CpuPlatformLib/CpuPlatformLibrary.c476
-rw-r--r--ReferenceCode/Haswell/Library/CpuPlatformLib/CpuPlatformLibrary.h31
-rw-r--r--ReferenceCode/Haswell/Library/OcPlatformLib.cif12
-rw-r--r--ReferenceCode/Haswell/Library/OcPlatformLib.mak20
-rw-r--r--ReferenceCode/Haswell/Library/OcPlatformLib.sdl32
-rw-r--r--ReferenceCode/Haswell/Library/OverclockingLib/OverclockingLib.inf69
-rw-r--r--ReferenceCode/Haswell/Library/OverclockingLib/OverclockingLibrary.c621
-rw-r--r--ReferenceCode/Haswell/Library/OverclockingLib/OverclockingLibrary.h352
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib.cif13
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib.mak40
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib.sdl26
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib/Ia32/Thunk16.asm238
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib/Ia32/ThunkLibIa32.cif9
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib/Ia32/x86Thunk.c245
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib/ThunkLib.inf67
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib/x64/FxRestore.asm45
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib/x64/FxSave.asm45
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib/x64/Thunk16.asm216
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib/x64/ThunkLibx64.cif11
-rw-r--r--ReferenceCode/Haswell/Library/ThunkLib/x64/x86Thunk.c272
-rw-r--r--ReferenceCode/Haswell/Library/TxtLib.cif11
-rw-r--r--ReferenceCode/Haswell/Library/TxtLib.mak16
-rw-r--r--ReferenceCode/Haswell/Library/TxtLib.sdl32
-rw-r--r--ReferenceCode/Haswell/Library/TxtLib/Ia32/TxtPeiLib.asm99
-rw-r--r--ReferenceCode/Haswell/Library/TxtLib/TxtLib.inf60
-rw-r--r--ReferenceCode/Haswell/PowerManagement/AcpiTables/PowerMgmtAcpiTables.cif19
-rw-r--r--ReferenceCode/Haswell/PowerManagement/AcpiTables/PowerMgmtAcpiTables.inf77
-rw-r--r--ReferenceCode/Haswell/PowerManagement/AcpiTables/PowerMgmtAcpiTables.mak168
-rw-r--r--ReferenceCode/Haswell/PowerManagement/AcpiTables/PowerMgmtAcpiTables.sdl87
-rw-r--r--ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/ApCst.asl146
-rw-r--r--ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/ApIst.asl408
-rw-r--r--ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/ApTst.asl481
-rw-r--r--ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/Cpu0Cst.asl319
-rw-r--r--ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/Cpu0Ist.asl163
-rw-r--r--ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/Cpu0Tst.asl258
-rw-r--r--ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/CpuPm.asl1061
-rw-r--r--ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/Ctdp.asl310
-rw-r--r--ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/LakeTiny.asl157
-rw-r--r--ReferenceCode/Haswell/PowerManagement/Dxe/IdleStates.c918
-rw-r--r--ReferenceCode/Haswell/PowerManagement/Dxe/MiscFunctions.c853
-rw-r--r--ReferenceCode/Haswell/PowerManagement/Dxe/PerformanceStates.c930
-rw-r--r--ReferenceCode/Haswell/PowerManagement/Dxe/PowerLimits.c1302
-rw-r--r--ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtCommon.h877
-rw-r--r--ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtDxe.cif19
-rw-r--r--ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtDxe.dxs38
-rw-r--r--ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtDxe.inf114
-rw-r--r--ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtDxe.mak82
-rw-r--r--ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtDxe.sdl25
-rw-r--r--ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtInit.c840
-rw-r--r--ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtInit.h127
-rw-r--r--ReferenceCode/Haswell/PowerManagement/Dxe/Thermal.c301
-rw-r--r--ReferenceCode/Haswell/PowerManagement/Smm/PowerMgmtS3.c333
-rw-r--r--ReferenceCode/Haswell/PowerManagement/Smm/PowerMgmtS3.cif13
-rw-r--r--ReferenceCode/Haswell/PowerManagement/Smm/PowerMgmtS3.dxs45
-rw-r--r--ReferenceCode/Haswell/PowerManagement/Smm/PowerMgmtS3.h68
-rw-r--r--ReferenceCode/Haswell/PowerManagement/Smm/PowerMgmtS3.inf97
-rw-r--r--ReferenceCode/Haswell/PowerManagement/Smm/PowerMgmtS3.mak64
-rw-r--r--ReferenceCode/Haswell/PowerManagement/Smm/PowerMgmtS3.sdl25
-rw-r--r--ReferenceCode/Haswell/Ppi/Cache/Cache.c25
-rw-r--r--ReferenceCode/Haswell/Ppi/Cache/Cache.h86
-rw-r--r--ReferenceCode/Haswell/Ppi/CpuPlatformPolicy/CpuPlatformPolicy.c43
-rw-r--r--ReferenceCode/Haswell/Ppi/CpuPlatformPolicy/CpuPlatformPolicy.h358
-rw-r--r--ReferenceCode/Haswell/Ppi/CpuPpiLib.cif18
-rw-r--r--ReferenceCode/Haswell/Ppi/CpuPpiLib.inf65
-rw-r--r--ReferenceCode/Haswell/Ppi/CpuPpiLib.mak21
-rw-r--r--ReferenceCode/Haswell/Ppi/CpuPpiLib.sdl31
-rw-r--r--ReferenceCode/Haswell/Ppi/TpmInitialized/TpmInitialized.c24
-rw-r--r--ReferenceCode/Haswell/Ppi/TpmInitialized/TpmInitialized.h29
-rw-r--r--ReferenceCode/Haswell/Ppi/TxtMemoryUnlocked/TxtMemoryUnlocked.c33
-rw-r--r--ReferenceCode/Haswell/Ppi/TxtMemoryUnlocked/TxtMemoryUnlocked.h32
-rw-r--r--ReferenceCode/Haswell/Protocol/CpuInfo/CpuInfo.c25
-rw-r--r--ReferenceCode/Haswell/Protocol/CpuInfo/CpuInfo.h79
-rw-r--r--ReferenceCode/Haswell/Protocol/CpuPlatformPolicy/CpuPlatformPolicy.c26
-rw-r--r--ReferenceCode/Haswell/Protocol/CpuPlatformPolicy/CpuPlatformPolicy.h329
-rw-r--r--ReferenceCode/Haswell/Protocol/CpuPlatformPolicy/CpuPmConfig.h302
-rw-r--r--ReferenceCode/Haswell/Protocol/CpuProtocolLib.cif27
-rw-r--r--ReferenceCode/Haswell/Protocol/CpuProtocolLib.inf75
-rw-r--r--ReferenceCode/Haswell/Protocol/CpuProtocolLib.mak28
-rw-r--r--ReferenceCode/Haswell/Protocol/CpuProtocolLib.sdl29
-rw-r--r--ReferenceCode/Haswell/Protocol/MpService/MpService.c24
-rw-r--r--ReferenceCode/Haswell/Protocol/MpService/MpService.h216
-rw-r--r--ReferenceCode/Haswell/Protocol/Pfat/Pfat.c45
-rw-r--r--ReferenceCode/Haswell/Protocol/Pfat/Pfat.h129
-rw-r--r--ReferenceCode/Haswell/Protocol/PiMpService/PiMpService.c24
-rw-r--r--ReferenceCode/Haswell/Protocol/PiMpService/PiMpService.h500
-rw-r--r--ReferenceCode/Haswell/Protocol/PowerMgmtInitDone/PowerMgmtInitDone.c42
-rw-r--r--ReferenceCode/Haswell/Protocol/PowerMgmtInitDone/PowerMgmtInitDone.h52
-rw-r--r--ReferenceCode/Haswell/Protocol/PpmGlobalNvsArea/PpmGlobalNvsArea.c31
-rw-r--r--ReferenceCode/Haswell/Protocol/PpmGlobalNvsArea/PpmGlobalNvsArea.h129
-rw-r--r--ReferenceCode/Haswell/Protocol/SmmThunk/SmmThunk.c25
-rw-r--r--ReferenceCode/Haswell/Protocol/SmmThunk/SmmThunk.h64
-rw-r--r--ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Dxe/CpuPolicyDxe.cif13
-rw-r--r--ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Dxe/CpuPolicyDxe.mak92
-rw-r--r--ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Dxe/CpuPolicyDxe.sdl58
-rw-r--r--ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Dxe/CpuPolicyInitDxe.c461
-rw-r--r--ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Dxe/CpuPolicyInitDxe.dxs42
-rw-r--r--ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Dxe/CpuPolicyInitDxe.h50
-rw-r--r--ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Dxe/CpuPolicyInitDxe.inf93
-rw-r--r--ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Pei/CpuPolicyInitPei.c268
-rw-r--r--ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Pei/CpuPolicyInitPei.dxs41
-rw-r--r--ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Pei/CpuPolicyInitPei.h55
-rw-r--r--ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Pei/CpuPolicyInitPei.inf87
-rw-r--r--ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Pei/CpuPolicyPei.cif13
-rw-r--r--ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Pei/CpuPolicyPei.mak139
-rw-r--r--ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Pei/CpuPolicyPei.sdl58
-rw-r--r--ReferenceCode/Haswell/SampleCode/CpuSampleCode.cif15
-rw-r--r--ReferenceCode/Haswell/SampleCode/Include/AslUpdateLib.h178
-rw-r--r--ReferenceCode/Haswell/SampleCode/Include/BootGuardRevocationLib.h35
-rw-r--r--ReferenceCode/Haswell/SampleCode/Include/Cpu.h63
-rw-r--r--ReferenceCode/Haswell/SampleCode/Include/FlashMap.h27
-rw-r--r--ReferenceCode/Haswell/SampleCode/Include/KscLib.h232
-rw-r--r--ReferenceCode/Haswell/SampleCode/Include/PeiKscLib.h224
-rw-r--r--ReferenceCode/Haswell/SampleCode/Include/SmmIoLib.h265
-rw-r--r--ReferenceCode/Haswell/SampleCode/Include/acpibuild.dsc96
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/AslUpdate/Dxe/DxeAslUpdateLib.c333
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/AslUpdate/Dxe/DxeAslUpdateLib.inf46
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/AslUpdate/Dxe/PpmAslUpdateLib.cif11
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/AslUpdate/Dxe/PpmAslUpdateLib.mak31
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/AslUpdate/Dxe/PpmAslUpdateLib.sdl29
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/BootGuardRevocationLib/Dxe/BootGuardRevocationLib.c34
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/BootGuardRevocationLib/Dxe/BootGuardRevocationLib.cif11
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/BootGuardRevocationLib/Dxe/BootGuardRevocationLib.inf73
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/BootGuardRevocationLib/Dxe/BootGuardRevocationLib.mak31
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/BootGuardRevocationLib/Dxe/BootGuardRevocationLib.sdl29
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/BootGuardTpmEventLogLib/BootGuardTpmEventLogLib.c838
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/BootGuardTpmEventLogLib/BootGuardTpmEventLogLib.cif11
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/BootGuardTpmEventLogLib/BootGuardTpmEventLogLib.h33
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/BootGuardTpmEventLogLib/BootGuardTpmEventLogLib.mak31
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/BootGuardTpmEventLogLib/BootGuardTpmEventLogLib.sdl29
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/DTSHookLib/Smm/DTSHookLib.c71
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/DTSHookLib/Smm/DTSHookLib.cif12
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/DTSHookLib/Smm/DTSHookLib.h27
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/DTSHookLib/Smm/DTSHookLib.inf49
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/DTSHookLib/Smm/DTSHookLib.mak15
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/DTSHookLib/Smm/DTSHookLib.sdl25
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/Ksc/Smm/SmmKscLib.c228
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/Ksc/Smm/SmmKscLib.cif11
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/Ksc/Smm/SmmKscLib.inf51
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/Ksc/Smm/SmmKscLib.mak15
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/Ksc/Smm/SmmKscLib.sdl25
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/SmmIo/SmmIo.c169
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/SmmIo/SmmIoLib.cif12
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/SmmIo/SmmIoLib.inf48
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/SmmIo/SmmIoLib.mak15
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/SmmIo/SmmIoLib.sdl25
-rw-r--r--ReferenceCode/Haswell/SampleCode/Library/SmmIo/SmmPciIo.c161
-rw-r--r--ReferenceCode/Haswell/SampleCode/Protocol/CpuSampleCodeProtocolLib.cif11
-rw-r--r--ReferenceCode/Haswell/SampleCode/Protocol/CpuSampleCodeProtocolLib.mak25
-rw-r--r--ReferenceCode/Haswell/SampleCode/Protocol/CpuSampleCodeProtocolLib.sdl24
-rw-r--r--ReferenceCode/Haswell/SampleCode/Protocol/TxtOneTouchOp/TxtOneTouchOp.c32
-rw-r--r--ReferenceCode/Haswell/SampleCode/Protocol/TxtOneTouchOp/TxtOneTouchOp.h106
-rw-r--r--ReferenceCode/Haswell/SampleCode/SecCore/CpuRcSec.cif20
-rw-r--r--ReferenceCode/Haswell/SampleCode/SecCore/CpuRcSec.mak27
-rw-r--r--ReferenceCode/Haswell/SampleCode/SecCore/CpuRcSec.sdl40
-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
-rw-r--r--ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchDxe.c631
-rw-r--r--ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchDxe.cif14
-rw-r--r--ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchDxe.dxs42
-rw-r--r--ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchDxe.h158
-rw-r--r--ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchDxe.inf113
-rw-r--r--ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchDxe.mak88
-rw-r--r--ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchDxe.sdl28
-rw-r--r--ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchOp.c178
-rw-r--r--ReferenceCode/Haswell/Txt/BiosAcm/HSW_BIOSAC_DBG_Rev1_5.BINbin0 -> 64576 bytes
-rw-r--r--ReferenceCode/Haswell/Txt/BiosAcm/HSW_BIOSAC_PRO_NPW_Rev1_5.BINbin0 -> 64576 bytes
-rw-r--r--ReferenceCode/Haswell/Txt/BiosAcm/HSW_BIOSAC_PRO_Rev1_5.BINbin0 -> 64576 bytes
-rw-r--r--ReferenceCode/Haswell/Txt/BiosAcm/TxtBiosAcm.cif14
-rw-r--r--ReferenceCode/Haswell/Txt/BiosAcm/TxtBiosAcm.inf33
-rw-r--r--ReferenceCode/Haswell/Txt/BiosAcm/TxtBiosAcm.mak13
-rw-r--r--ReferenceCode/Haswell/Txt/BiosAcm/TxtBiosAcm.sdl39
-rw-r--r--ReferenceCode/Haswell/Txt/BiosAcm/makefile.new63
-rw-r--r--ReferenceCode/Haswell/Txt/Tools/Apfixup.txt33
-rw-r--r--ReferenceCode/Haswell/Txt/Tools/Stafixup.exebin0 -> 20992 bytes
-rw-r--r--ReferenceCode/Haswell/Txt/Tools/TxtTools.cif10
-rw-r--r--ReferenceCode/Haswell/Txt/Tools/TxtTools.sdl23
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.c171
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.cif18
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.dxs50
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.inf117
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.mak72
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.sdl27
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxeLib.c1080
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxeLib.h289
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxeOem.c78
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/Mmx64.inc494
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/TxtDxeAp.asm364
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/TxtDxeBsp.asm712
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/TxtPeiAp.asm16305
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/TxtPeiAp.inf35
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/TxtPeiApV7.inf35
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/TxtPeiBsp.asm1387
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/makefile.new69
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.c241
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.dxs49
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.inf104
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.mak105
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.sdl86
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPeiLib.c1045
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPeiLib.h560
-rw-r--r--ReferenceCode/Haswell/Txt/TxtInit/Pei/Txtpei.cif19
341 files changed, 66385 insertions, 0 deletions
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/CacheData.c b/ReferenceCode/Haswell/CpuInit/Dxe/CacheData.c
new file mode 100644
index 0000000..f68c151
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/CacheData.c
@@ -0,0 +1,515 @@
+/** @file
+ Processor Cache data records.
+
+@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 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
+
+**/
+
+///
+/// External include files do NOT need to be explicitly specified in real EDKII
+/// environment
+///
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "CpuAccess.h"
+#include "CacheData.h"
+#endif
+///
+/// This is the VFR compiler generated header file which defines the
+/// string identifiers.
+///
+#include "CpuInitDxeStrDefs.h"
+
+extern EFI_DATA_HUB_PROTOCOL *mDataHub;
+extern EFI_SUBCLASS_TYPE1_HEADER mCpuDataRecordHeader;
+
+EFI_CACHE_CONVERTER mCacheConverter[] = {
+ {
+ 1,
+ 0x09,
+ 32,
+ EfiCacheAssociativity4Way,
+ EfiCacheTypeInstruction
+ },
+ {
+ 1,
+ 0x0D,
+ 16,
+ EfiCacheAssociativity4Way,
+ EfiCacheTypeData
+ },
+ {
+ 2,
+ 0x21,
+ 256,
+ EfiCacheAssociativity8Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 1,
+ 0x2C,
+ 32,
+ EfiCacheAssociativity8Way,
+ EfiCacheTypeData
+ },
+ {
+ 2,
+ 0x40,
+ 0,
+ EfiCacheAssociativityUnknown,
+ EfiCacheTypeUnknown
+ },
+ {
+ 3,
+ 0xD0,
+ 512,
+ EfiCacheAssociativity4Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xD1,
+ 1024,
+ EfiCacheAssociativity4Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xD2,
+ 2048,
+ EfiCacheAssociativity4Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xD3,
+ 4096,
+ EfiCacheAssociativity4Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xD4,
+ 8192,
+ EfiCacheAssociativity4Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xD6,
+ 1024,
+ EfiCacheAssociativity8Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xD7,
+ 2048,
+ EfiCacheAssociativity8Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xD8,
+ 4096,
+ EfiCacheAssociativity8Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xD9,
+ 8192,
+ EfiCacheAssociativity8Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xDA,
+ 12288,
+ EfiCacheAssociativity8Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xDC,
+ 1536,
+ EfiCacheAssociativity12Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xDD,
+ 3072,
+ EfiCacheAssociativity12Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xDE,
+ 6144,
+ EfiCacheAssociativity12Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xDF,
+ 12288,
+ EfiCacheAssociativity12Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xE0,
+ 18432,
+ EfiCacheAssociativity12Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xE2,
+ 2048,
+ EfiCacheAssociativity16Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xE3,
+ 4096,
+ EfiCacheAssociativity16Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xE4,
+ 8192,
+ EfiCacheAssociativity16Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xE5,
+ 16384,
+ EfiCacheAssociativity16Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xE6,
+ 24576,
+ EfiCacheAssociativity16Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xEA,
+ 12288,
+ EfiCacheAssociativity24Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xEB,
+ 18432,
+ EfiCacheAssociativity24Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 3,
+ 0xEC,
+ 24567,
+ EfiCacheAssociativity24Way,
+ EfiCacheTypeUnified
+ },
+ {
+ 0,
+ 0xFF,
+ 0,
+ 0,
+ 0
+ }
+};
+
+///
+/// Convert Cache Type Field to SMBIOS format
+///
+#define SMBIOS_CACHE_TYPE_MAX 5
+UINT8 SmbiosCacheTypeFieldConverter[SMBIOS_CACHE_TYPE_MAX] = {
+ EfiCacheTypeUnknown,
+ EfiCacheTypeData,
+ EfiCacheTypeInstruction,
+ EfiCacheTypeUnified,
+ EfiCacheTypeOther
+};
+
+UINT8 mCacheInstance[EFI_CACHE_LMAX] = { 0, 0, 0, 0 };
+
+EFI_SUBCLASS_TYPE1_HEADER mCacheDataRecordHeader = {
+ EFI_CACHE_SUBCLASS_VERSION, ///< Version
+ sizeof (EFI_SUBCLASS_TYPE1_HEADER), ///< Header Size
+ 0, ///< Instance, Initialize later
+ 0, ///< SubInstance, Initialize later to Cache Level
+ 0 ///< RecordType, Initialize later
+};
+
+/**
+ This function gets called with the processor number and will log all cache data to data hub
+ pertaining to this processor.
+
+ @param[in] CpuNumber - Processor Number
+ @param[in] CacheInformation - Cache information get from cpuid instruction
+
+ @retval EFI_OUT_OF_RESOURCES - Failed to allocate required POOL for record buffer.
+ @retval EFI_SUCCESS - successful to update cache data
+**/
+EFI_STATUS
+InitializeCacheData (
+ IN UINTN CpuNumber,
+ IN EFI_CPUID_REGISTER *CacheInformation
+ )
+{
+ EFI_STATUS Status;
+ UINT32 HeaderSize;
+ UINT32 TotalSize;
+ CPU_CACHE_DATA_RECORD_BUFFER RecordBuffer;
+ UINT8 Index1;
+ UINT8 CacheLevel;
+ UINT8 LxCacheType;
+ UINT32 Ways;
+ UINT32 Partitions;
+ UINT32 LineSets;
+ UINT32 Sets;
+ UINT32 LxCacheSize;
+ EFI_CPUID_REGISTER CpuidRegisters;
+
+ ///
+ /// Only log CPU socket level information.
+ ///
+ if (CpuNumber != 0) {
+ return EFI_SUCCESS;
+ }
+
+ mCacheDataRecordHeader.Instance = (UINT16) (CpuNumber + 1);
+
+ HeaderSize = sizeof (EFI_SUBCLASS_TYPE1_HEADER);
+ RecordBuffer.Raw = AllocatePool (HeaderSize + CPU_CACHE_DATA_MAXIMUM_LENGTH);
+ if (RecordBuffer.Raw == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Index1 = 0;; Index1++) {
+ EfiCpuidExt (CPUID_CACHE_PARAMS, Index1, &CpuidRegisters);
+ if ((CpuidRegisters.RegEax & V_CPUID_CACHE_TYPE_MASK) == 0) {
+ break;
+ }
+
+ Ways = ((CpuidRegisters.RegEbx >> B_CPUID_CACHE_PARAMS_WAYS_SHIFT) & 0x3FF) + 1;
+ Partitions = ((CpuidRegisters.RegEbx >> B_CPUID_CACHE_PARAMS_PARTITIONS_SHIFT) & 0x3FF) + 1;
+ LineSets = (CpuidRegisters.RegEbx & 0xFFF) + 1;
+ Sets = CpuidRegisters.RegEcx + 1;
+
+ CacheLevel = (UINT8) (CpuidRegisters.RegEax & V_CPUID_CACHE_LEVEL_MASK) >> B_CPUID_CACHE_LEVEL_SHIFT;
+ LxCacheSize = (Ways * Partitions * LineSets * Sets) / 1024;
+ LxCacheType = (UINT8) (CpuidRegisters.RegEax & V_CPUID_CACHE_TYPE_MASK);
+
+ CopyMem (RecordBuffer.Raw, &mCacheDataRecordHeader, HeaderSize);
+
+ mCacheInstance[CacheLevel - 1]++;
+ RecordBuffer.DataRecord->DataRecordHeader.Instance = mCacheInstance[CacheLevel - 1];
+ RecordBuffer.DataRecord->DataRecordHeader.SubInstance = CacheLevel;
+
+ ///
+ /// Record Type 1
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = CacheSizeRecordType;
+ TotalSize = HeaderSize + sizeof (EFI_CACHE_SIZE_DATA);
+ RecordBuffer.DataRecord->VariableRecord.CacheSize.Value = (UINT16) LxCacheSize;
+ RecordBuffer.DataRecord->VariableRecord.CacheSize.Exponent = 10;
+ Status = LogCacheData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 2
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = MaximumSizeCacheRecordType;
+ TotalSize = HeaderSize + sizeof (EFI_MAXIMUM_CACHE_SIZE_DATA);
+ RecordBuffer.DataRecord->VariableRecord.MaximumCacheSize.Value = (UINT16) LxCacheSize;
+ RecordBuffer.DataRecord->VariableRecord.MaximumCacheSize.Exponent = 10;
+ Status = LogCacheData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 3
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = CacheSpeedRecordType;
+ TotalSize = HeaderSize + sizeof (EFI_CACHE_SPEED_DATA);
+ RecordBuffer.DataRecord->VariableRecord.CacheSpeed.Exponent = 0;
+ RecordBuffer.DataRecord->VariableRecord.CacheSpeed.Value = 0;
+ Status = LogCacheData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 4
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = CacheSocketRecordType;
+ TotalSize = HeaderSize + sizeof (EFI_CACHE_SOCKET_DATA);
+ RecordBuffer.DataRecord->VariableRecord.CacheSocket = 0;
+ ///
+ /// CacheDesignation[Index1];
+ ///
+ Status = LogCacheData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 5
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = CacheSramTypeRecordType;
+ TotalSize = HeaderSize + sizeof (EFI_CACHE_SRAM_TYPE_DATA);
+ ZeroMem (
+ &RecordBuffer.DataRecord->VariableRecord.CacheSramType,
+ sizeof (EFI_CACHE_SRAM_TYPE_DATA)
+ );
+ RecordBuffer.DataRecord->VariableRecord.CacheSramType.Synchronous = TRUE;
+ Status = LogCacheData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 6, since record same as Type 5
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = CacheInstalledSramTypeRecordType;
+ Status = LogCacheData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 7
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = CacheErrorTypeRecordType;
+ TotalSize = HeaderSize + sizeof (EFI_CACHE_ERROR_TYPE_DATA);
+ RecordBuffer.DataRecord->VariableRecord.CacheErrorType = EfiCacheErrorSingleBit;
+ Status = LogCacheData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 8
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = CacheTypeRecordType;
+ TotalSize = HeaderSize + sizeof (EFI_CACHE_TYPE_DATA);
+ ///
+ /// If cache type is larger or equal than 5, this is undefined type so mark it as "Other" Cache type.
+ ///
+ if (LxCacheType >= SMBIOS_CACHE_TYPE_MAX) {
+ LxCacheType = SMBIOS_CACHE_TYPE_MAX - 1;
+ }
+ RecordBuffer.DataRecord->VariableRecord.CacheType = SmbiosCacheTypeFieldConverter[LxCacheType];
+ Status = LogCacheData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 9
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = CacheAssociativityRecordType;
+ TotalSize = HeaderSize + sizeof (EFI_CACHE_ASSOCIATIVITY_DATA);
+ ///
+ /// Convert Associativity Ways to SMBIOS format
+ ///
+ switch (Ways) {
+ case 2:
+ Ways = EfiCacheAssociativity2Way;
+ break;
+ case 4:
+ Ways = EfiCacheAssociativity4Way;
+ break;
+ case 8:
+ Ways = EfiCacheAssociativity8Way;
+ break;
+ case 12:
+ Ways = EfiCacheAssociativity12Way;
+ break;
+ case 16:
+ Ways = EfiCacheAssociativity16Way;
+ break;
+ case 24:
+ Ways = EfiCacheAssociativity24Way;
+ break;
+ case 32:
+ Ways = EfiCacheAssociativity32Way;
+ break;
+ case 48:
+ Ways = EfiCacheAssociativity48Way;
+ break;
+ case 64:
+ Ways = EfiCacheAssociativity64Way;
+ break;
+ default:
+ Ways = EfiCacheAssociativityOther;
+ break;
+ }
+ RecordBuffer.DataRecord->VariableRecord.CacheAssociativity = Ways;
+ Status = LogCacheData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 10
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = CacheConfigRecordType;
+ TotalSize = HeaderSize + sizeof (EFI_CACHE_CONFIGURATION_DATA);
+ RecordBuffer.DataRecord->VariableRecord.CacheConfig.Level = CacheLevel;
+ RecordBuffer.DataRecord->VariableRecord.CacheConfig.Socketed = EFI_CACHE_NOT_SOCKETED;
+ RecordBuffer.DataRecord->VariableRecord.CacheConfig.Reserved2 = 0;
+ RecordBuffer.DataRecord->VariableRecord.CacheConfig.Location = EfiCacheInternal;
+ RecordBuffer.DataRecord->VariableRecord.CacheConfig.Enable = EFI_CACHE_ENABLED;
+ RecordBuffer.DataRecord->VariableRecord.CacheConfig.OperationalMode = EfiCacheWriteBack;
+ RecordBuffer.DataRecord->VariableRecord.CacheConfig.Reserved1 = 0;
+ Status = LogCacheData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Cache Association. Processor Record Type 17
+ ///
+ TotalSize = HeaderSize + sizeof (EFI_CACHE_ASSOCIATION_DATA);
+ RecordBuffer.DataRecord->VariableRecord.CacheAssociation.ProducerName = gEfiProcessorProducerGuid;
+ ///
+ /// RecordBuffer.DataRecord->VariableRecord.CacheAssociation.ProducerInstance = (UINT16)Instance;
+ ///
+ RecordBuffer.DataRecord->VariableRecord.CacheAssociation.Instance = RecordBuffer.DataRecord->DataRecordHeader.Instance;
+ RecordBuffer.DataRecord->VariableRecord.CacheAssociation.SubInstance = RecordBuffer.DataRecord->DataRecordHeader.SubInstance;
+ CopyMem (RecordBuffer.Raw, &mCpuDataRecordHeader, HeaderSize);
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = CacheAssociationRecordType;
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+ }
+
+ FreePool (RecordBuffer.Raw);
+ return EFI_SUCCESS;
+}
+
+/**
+ Log cache data into data hub
+
+ @param[in] DataHub - Pointer to the DataHub protocol that will be updated
+ @param[in] Buffer - Data buffer which will be updated into DataHub
+ @param[in] Size - The size of data buffer
+
+ @retval EFI_STATUS - status code for logging data into dat hub
+**/
+EFI_STATUS
+LogCacheData (
+ EFI_DATA_HUB_PROTOCOL *DataHub,
+ UINT8 *Buffer,
+ UINT32 Size
+ )
+{
+ EFI_STATUS Status;
+
+ Status = DataHub->LogData (
+ DataHub,
+ &gEfiCacheSubClassGuid,
+ &gEfiProcessorProducerGuid,
+ EFI_DATA_RECORD_CLASS_DATA,
+ Buffer,
+ Size
+ );
+ return Status;
+}
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/CacheData.h b/ReferenceCode/Haswell/CpuInit/Dxe/CacheData.h
new file mode 100644
index 0000000..57579eb
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/CacheData.h
@@ -0,0 +1,91 @@
+/** @file
+ Header file for CPU Data File
+
+@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 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
+**/
+#ifndef _CACHE_DATA_H_
+#define _CACHE_DATA_H_
+
+#include "CpuInitDxe.h"
+
+///
+/// Platform-specific definitions
+///
+#define CPU_CACHE_DATA_MAXIMUM_LENGTH 0x100
+
+typedef union {
+ EFI_CACHE_DATA_RECORD *DataRecord;
+ UINT8 *Raw;
+} CPU_CACHE_DATA_RECORD_BUFFER;
+
+typedef struct {
+ UINT8 CacheLevel;
+ UINT8 CacheDescriptor;
+ UINT16 CacheSizeinKB;
+ EFI_CACHE_ASSOCIATIVITY_DATA Associativity;
+ EFI_CACHE_TYPE_DATA Type;
+} EFI_CACHE_CONVERTER;
+
+/**
+ This function gets called with the processor number and will log all cache data to data hub
+ pertaining to this processor.
+
+ @param[in] CpuNumber - Processor Number
+ @param[in] CacheInformation - Cache information get from cpuid instruction
+
+ @retval EFI_OUT_OF_RESOURCES - Failed to allocate required POOL for record buffer.
+ @retval EFI_SUCCESS - successful to update cache data
+**/
+EFI_STATUS
+InitializeCacheData (
+ IN UINTN CpuNumber,
+ IN EFI_CPUID_REGISTER *CacheInformation
+ );
+
+/**
+ Log cache data into data hub
+
+ @param[in] DataHub - Pointer to the DataHub protocol that will be updated
+ @param[in] Buffer - Data buffer which will be updated into DataHub
+ @param[in] Size - The size of data buffer
+
+ @retval EFI_STATUS - status code for logging data into dat hub
+**/
+EFI_STATUS
+LogCacheData (
+ EFI_DATA_HUB_PROTOCOL *DataHub,
+ UINT8 *Buffer,
+ UINT32 Size
+ );
+
+/**
+ Log CPU data into data hub
+
+ @param[in] DataHub - point to data hub that will be updated
+ @param[in] Buffer - the buffer which will be updated into data hub
+ @param[in] Size - size of the buffer
+
+ @retval EFI_STATUS - status returned when updating Data hub
+**/
+EFI_STATUS
+LogCpuData (
+ EFI_DATA_HUB_PROTOCOL *DataHub,
+ UINT8 *Buffer,
+ UINT32 Size
+ );
+
+#endif
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/CpuFvi.c b/ReferenceCode/Haswell/CpuInit/Dxe/CpuFvi.c
new file mode 100644
index 0000000..7559980
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/CpuFvi.c
@@ -0,0 +1,62 @@
+/** @file
+ CPU Firmware Version Info implementation.
+
+@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
+**/
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "CpuInitDxe.h"
+#endif
+
+FVI_ELEMENT_AND_FUNCTION mCpuFviElementsData[] = {
+ {
+ DEFAULT_FVI_ELEMENT_DATA(CPU),
+ NULL
+ },
+ {
+ {
+ 1,
+ 0,
+ UCODE_VERSION,
+ UCODE_FVI_STRING,
+ {
+ 0
+ },
+ },
+ NULL
+ },
+ {
+ {
+ 1,
+ 0,
+ TXT_VERSION,
+ TXT_FVI_STRING,
+ {
+ 0
+ },
+ },
+ NULL
+ }
+};
+
+FVI_DATA_HUB_CALLBACK_CONTEXT mCpuFviVersionData = {
+ MISC_SUBCLASS_FVI_HEADER_ENTRY(CPU),
+ mCpuFviElementsData,
+};
+
+UINTN mCpuFviElements = sizeof (mCpuFviElementsData) / sizeof (FVI_ELEMENT_AND_FUNCTION);
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxe.c b/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxe.c
new file mode 100644
index 0000000..93ec58e
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxe.c
@@ -0,0 +1,1085 @@
+/** @file
+ Cpu driver, which initializes CPU and implements CPU Architecture
+ Protocol as defined in Framework specification.
+
+@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 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
+
+**/
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "CpuInitDxe.h"
+#include "ProcessorData.h"
+#include "CacheData.h"
+#include "Exception.h"
+#include "PfatDefinitions.h"
+#include "BootGuardLibrary.h"
+#include "BootGuardRevocationLib.h"
+
+#define SAMPLE_TICK_COUNT 1000
+
+#endif
+
+#include <token.h>
+extern UINT64 mValidMtrrAddressMask;
+extern UINT64 mValidMtrrBitsMask;
+extern EFI_CPU_MICROCODE_HEADER **mMicrocodePointerBuffer;
+extern UINT8 CpuInitDxeStrings[];
+
+#if (EFI_SPECIFICATION_VERSION >= 0x2000A)
+EFI_HANDLE mDriverHandle;
+EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;
+#else
+EFI_HII_PROTOCOL *mHii;
+#endif
+EFI_SMM_BASE_PROTOCOL *mSmmBaseProtocol = NULL;
+VOID *mSmmBaseRegistration;
+EFI_METRONOME_ARCH_PROTOCOL *mMetronome;
+DXE_CPU_PLATFORM_POLICY_PROTOCOL *mPlatformCpu = NULL;
+EFI_HII_HANDLE mStringHandle;
+BOOLEAN mIsFlushingGCD = TRUE;
+UINT8 mSmmbaseSwSmiNumber;
+BOOLEAN mVariableMtrrChanged;
+BOOLEAN mFixedMtrrChanged;
+UINT64 mCpuFrequency = 0;
+
+EFI_EVENT gReadyToBootEvent;
+EFI_CPU_INTERRUPT_HANDLER mExternalVectorTable[0x100];
+BOOLEAN mInterruptState = FALSE;
+
+///
+/// The Cpu Architectural Protocol that this Driver produces
+///
+EFI_CPU_ARCH_PROTOCOL gCpu = {
+ FlushCpuDataCache,
+ EnableInterrupt,
+ DisableInterrupt,
+ CpuGetInterruptState,
+ Init,
+ RegisterInterruptHandler,
+ GetTimerValue,
+ SetMemoryAttributes,
+ 1, ///< NumberOfTimers
+ 4, ///< DmaBufferAlignment
+};
+
+/**
+ Decide if the CPU is executing in SMM mode
+
+ @retval TRUE - The CPU is executing in SMM mode
+ @retval FALSE - The CPU is not executing in SMM mode
+**/
+BOOLEAN
+ExecutionInSmm (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN InSmm;
+
+ if (mSmmBaseProtocol == NULL) {
+ return FALSE;
+ }
+
+ Status = mSmmBaseProtocol->InSmm (mSmmBaseProtocol, &InSmm);
+ ASSERT_EFI_ERROR (Status);
+ return InSmm;
+}
+
+/**
+ Flush CPU data cache. If the instruction cache is fully coherent
+ with all DMA operations then function can just return EFI_SUCCESS.
+
+ @param[in] This - Protocol instance structure
+ @param[in] Start - Physical address to start flushing from.
+ @param[in] Length - Number of bytes to flush. Round up to chipset
+ granularity.
+ @param[in] FlushType - Specifies the type of flush operation to perform.
+
+ @retval EFI_SUCCESS - If cache was flushed
+ @exception EFI_UNSUPPORTED - If flush type is not supported.
+ @retval EFI_DEVICE_ERROR - If requested range could not be flushed.
+**/
+EFI_STATUS
+EFIAPI
+FlushCpuDataCache (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length,
+ IN EFI_CPU_FLUSH_TYPE FlushType
+ )
+{
+ if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {
+ AsmWbinvd ();
+ return EFI_SUCCESS;
+ } else if (FlushType == EfiCpuFlushTypeInvalidate) {
+ EfiInvd ();
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+}
+
+/**
+ Enables CPU interrupts.
+
+ @param[in] This - Protocol instance structure
+
+ @retval EFI_SUCCESS - If interrupts were enabled in the CPU
+ @retval EFI_DEVICE_ERROR - If interrupts could not be enabled on the CPU.
+**/
+EFI_STATUS
+EFIAPI
+EnableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ )
+{
+ if (!ExecutionInSmm ()) {
+ CpuEnableInterrupt ();
+ }
+
+ mInterruptState = TRUE;
+ return EFI_SUCCESS;
+}
+
+/**
+ Disables CPU interrupts.
+
+ @param[in] This - Protocol instance structure
+
+ @retval EFI_SUCCESS - If interrupts were disabled in the CPU.
+**/
+EFI_STATUS
+EFIAPI
+DisableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ )
+{
+ CpuDisableInterrupt ();
+
+ mInterruptState = FALSE;
+ return EFI_SUCCESS;
+}
+
+/**
+ Return the state of interrupts.
+
+ @param[in] This - Protocol instance structure
+ @param[in] State - Pointer to the CPU's current interrupt state
+
+ @retval EFI_SUCCESS - If interrupts were disabled in the CPU.
+ @retval EFI_INVALID_PARAMETER - State is NULL.
+**/
+EFI_STATUS
+EFIAPI
+CpuGetInterruptState (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ OUT BOOLEAN *State
+ )
+{
+ if (State == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *State = mInterruptState;
+ return EFI_SUCCESS;
+}
+
+/**
+ Generates an INIT to the CPU
+
+ @param[in] This - Protocol instance structure
+ @param[in] InitType - Type of CPU INIT to perform
+
+ @retval EFI_SUCCESS - If CPU INIT occurred. This value should never be seen
+ @retval EFI_DEVICE_ERROR - If CPU INIT failed.
+ @exception EFI_UNSUPPORTED - Requested type of CPU INIT not supported.
+**/
+EFI_STATUS
+EFIAPI
+Init (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_CPU_INIT_TYPE InitType
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Registers a function to be called from the CPU interrupt handler.
+
+ @param[in] This - Protocol instance structure
+ @param[in] InterruptType - Defines which interrupt to hook.
+ IA-32 valid range is 0x00 through 0xFF
+ @param[in] InterruptHandler - A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER
+ that is called when a processor interrupt occurs.
+ A null pointer is an error condition.
+
+ @retval EFI_SUCCESS - If handler installed or uninstalled.
+ @retval EFI_ALREADY_STARTED - InterruptHandler is not NULL, and a handler for
+ InterruptType was previously installed
+ @retval EFI_INVALID_PARAMETER - InterruptHandler is NULL, and a handler for
+ InterruptType was not previously installed.
+ @exception EFI_UNSUPPORTED - The interrupt specified by InterruptType is not supported.
+**/
+EFI_STATUS
+EFIAPI
+RegisterInterruptHandler (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ )
+{
+ if (InterruptType < 0 || InterruptType > 0xff) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (InterruptHandler == NULL && mExternalVectorTable[InterruptType] == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (InterruptHandler != NULL && mExternalVectorTable[InterruptType] != NULL) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ mExternalVectorTable[InterruptType] = InterruptHandler;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+GetTimerValue (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ )
+/**
+ Returns a timer value from one of the CPU's internal timers. There is no
+ inherent time interval between ticks but is a function of the CPU frequency.
+
+ @param[in] This - Protocol instance structure.
+ @param[in] TimerIndex - Specifies which CPU timer is requested.
+ @param[in] TimerValue - Pointer to the returned timer value.
+ @param[in] TimerPeriod - A pointer to the amount of time that passes in femtoseconds (10-15) for each
+ increment of TimerValue. If TimerValue does not increment at a predictable
+ rate, then 0 is returned. The amount of time that has passed between two calls to
+ GetTimerValue() can be calculated with the formula
+ (TimerValue2 - TimerValue1) * TimerPeriod. This parameter is optional and may be NULL.
+
+ @retval EFI_SUCCESS - If the CPU timer count was returned.
+ @exception EFI_UNSUPPORTED - If the CPU does not have any readable timers.
+ @retval EFI_DEVICE_ERROR - If an error occurred while reading the timer.
+ @retval EFI_INVALID_PARAMETER - TimerIndex is not valid or TimerValue is NULL.
+**/
+{
+ UINT64 Actual;
+
+ if (TimerValue == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (TimerIndex != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *TimerValue = EfiReadTsc ();
+
+ if (TimerPeriod != NULL) {
+ GetActualFrequency (mMetronome, &Actual);
+ *TimerPeriod = DivU64x32 (1000000000, (UINT32) Actual);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set memory cacheability attributes for given range of memeory
+
+ @param[in] This - Protocol instance structure
+ @param[in] BaseAddress - Specifies the start address of the memory range
+ @param[in] Length - Specifies the length of the memory range
+ @param[in] Attributes - The memory cacheability for the memory range
+
+ @retval EFI_SUCCESS - If the cacheability of that memory range is set successfully
+ @exception EFI_UNSUPPORTED - If the desired operation cannot be done
+ @retval EFI_INVALID_PARAMETER - The input parameter is not correct, such as Length = 0
+**/
+EFI_STATUS
+EFIAPI
+SetMemoryAttributes (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ )
+{
+ EFI_STATUS Status;
+ UINT64 TempQword;
+ UINT32 MsrNum;
+ UINTN MtrrNumber;
+ BOOLEAN Positive;
+ BOOLEAN OverLap;
+#define SKIP_ALIGN_CHECK 0
+#if SKIP_ALIGN_CHECK
+ UINT32 Remainder;
+#endif
+ EFI_MP_SERVICES_PROTOCOL *MpService;
+ EFI_STATUS Status1;
+ UINT32 VariableMtrrLimit;
+ UINT32 SmiEnVal;
+ BOOLEAN InterruptState;
+ UINT8 MasterIrq,SlaveIrq;
+
+ mFixedMtrrChanged = FALSE;
+ mVariableMtrrChanged = FALSE;
+
+ VariableMtrrLimit = (UINT32) (AsmReadMsr64 (IA32_MTRR_CAP) & B_IA32_MTRR_VARIABLE_SUPPORT);
+
+ if (mIsFlushingGCD) {
+ return EFI_SUCCESS;
+ }
+
+ TempQword = 0;
+
+ ///
+ /// Check for invalid parameter
+ ///
+ if (Length == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((BaseAddress &~mValidMtrrAddressMask) != 0 || (Length &~mValidMtrrAddressMask) != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ switch (Attributes) {
+ case EFI_MEMORY_UC:
+ Attributes = CACHE_UNCACHEABLE;
+ break;
+
+ case EFI_MEMORY_WC:
+ Attributes = CACHE_WRITECOMBINING;
+ break;
+
+ case EFI_MEMORY_WT:
+ Attributes = CACHE_WRITETHROUGH;
+ break;
+
+ case EFI_MEMORY_WP:
+ Attributes = CACHE_WRITEPROTECTED;
+ break;
+
+ case EFI_MEMORY_WB:
+ Attributes = CACHE_WRITEBACK;
+ break;
+
+ default:
+ return EFI_UNSUPPORTED;
+ }
+
+ ///
+ /// Check if Fixed MTRR
+ ///
+ Status = EFI_SUCCESS;
+ while ((BaseAddress < (1 << 20)) && (Length > 0) && Status == EFI_SUCCESS) {
+ Status = CalculateFixedMtrr (Attributes, &BaseAddress, &Length);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ MasterIrq = IoRead8(0x21); //save current irq mask
+ SlaveIrq = IoRead8(0xA1);
+ IoWrite8(0x21,0xFF);
+ IoWrite8(0xA1,0xFF);
+
+ CpuGetInterruptState (&gCpu, &InterruptState);
+ if (InterruptState) {
+ DisableInterrupt (&gCpu);
+ }
+ SmiEnVal = IoRead32(PM_BASE_ADDRESS + 0x30); // Save SMI Control and Enable Reg.
+ IoWrite32(PM_BASE_ADDRESS + 0x30, 0); // Disable SMI
+
+ if (mFixedMtrrChanged) {
+ ProgramFixedMtrr ();
+ }
+
+ if (Length == 0) {
+ ///
+ /// Just Fixed MTRR. NO need to go through Variable MTRR
+ ///
+ goto Done;
+ }
+
+ ///
+ /// since mem below 1m will be override by fixed mtrr, we can set it to 0 to save mtrr.
+ ///
+ if (BaseAddress == 0x100000) {
+ BaseAddress = 0;
+ Length += 0x100000;
+ }
+
+ ///
+ /// Check memory base address alignment
+ ///
+#if SKIP_ALIGN_CHECK
+ DivU64x32Remainder (BaseAddress, (UINT32) Power2MaxMemory (LShiftU64 (Length, 1)), &Remainder);
+ if (Remainder != 0) {
+ DivU64x32Remainder (BaseAddress, (UINT32) Power2MaxMemory (Length), &Remainder);
+ if (Remainder != 0) {
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+ }
+#endif
+
+ ///
+ /// Check overlap
+ ///
+ GetMemoryAttribute ();
+ OverLap = CheckMemoryAttributeOverlap (BaseAddress, BaseAddress + Length - 1);
+ if (OverLap) {
+ Status = CombineMemoryAttribute (Attributes, &BaseAddress, &Length);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ if (Length == 0) {
+ ///
+ /// combine successfully
+ ///
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+ } else {
+ if (Attributes == CACHE_UNCACHEABLE) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+ }
+
+ ///
+ /// Program Variable MTRRs
+ ///
+ if (mUsedMtrr >= VariableMtrrLimit) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ ///
+ /// Find first unused MTRR
+ ///
+ for (MsrNum = CACHE_VARIABLE_MTRR_BASE; MsrNum < (CACHE_VARIABLE_MTRR_BASE + VariableMtrrLimit * 2 - 1); MsrNum += 2) {
+ if ((AsmReadMsr64 (MsrNum + 1) & B_CACHE_MTRR_VALID) == 0) {
+ break;
+ }
+ }
+
+ TempQword = Length;
+ if (TempQword == Power2MaxMemory (TempQword)) {
+ ProgramVariableMtrr (
+ MsrNum,
+ BaseAddress,
+ Length,
+ Attributes
+ );
+ } else {
+ GetDirection (TempQword, &MtrrNumber, &Positive);
+ if ((mUsedMtrr + MtrrNumber) > VariableMtrrLimit) {
+ goto Done;
+ }
+ if (!Positive) {
+ Length = Power2MaxMemory (LShiftU64 (TempQword, 1));
+ ProgramVariableMtrr (
+ MsrNum,
+ BaseAddress,
+ Length,
+ Attributes
+ );
+ BaseAddress += TempQword;
+ TempQword = Length - TempQword;
+ Attributes = CACHE_UNCACHEABLE;
+ }
+ do {
+ ///
+ /// Find unused MTRR
+ ///
+ for (; MsrNum < (CACHE_VARIABLE_MTRR_BASE + VariableMtrrLimit * 2 - 1); MsrNum += 2) {
+ if ((AsmReadMsr64 (MsrNum + 1) & B_CACHE_MTRR_VALID) == 0) {
+ break;
+ }
+ }
+ Length = Power2MaxMemory (TempQword);
+ ProgramVariableMtrr (
+ MsrNum,
+ BaseAddress,
+ Length,
+ Attributes
+ );
+ BaseAddress += Length;
+ TempQword -= Length;
+ } while (TempQword);
+ }
+
+Done:
+ Status1 = gBS->LocateProtocol (
+ &gEfiMpServiceProtocolGuid,
+ NULL,
+ (VOID **) &MpService
+ );
+
+ if (!EFI_ERROR (Status1)) {
+ if (mVariableMtrrChanged || mFixedMtrrChanged) {
+ ///
+ /// PERF_START (NULL, L"CacheSync", NULL, 0);
+ ///
+ ReadMtrrRegisters ();
+ Status1 = MpService->StartupAllAPs (
+ MpService,
+ MpMtrrSynchUp,
+ FALSE,
+ NULL,
+ 0,
+ NULL,
+ NULL
+ );
+ ///
+ /// PERF_END (NULL, L"CacheSync", NULL, 0);
+ ///
+ }
+ }
+
+ IoWrite32(PM_BASE_ADDRESS + 0x30, SmiEnVal); // Restore SMI Control and Enable Reg.
+ if (InterruptState) {
+ EnableInterrupt (&gCpu);
+ }
+ IoWrite8(0x21,MasterIrq); //restore irq mask
+ IoWrite8(0xA1,SlaveIrq);
+ return Status;
+}
+
+/**
+ Initialize the SmmBase pointer when SmmBase protocol get installed
+
+ @param[in] Event - Event whose notification function is being invoked.
+ @param[in] Context - Pointer to the notification functions context, which is implementation dependent.
+**/
+VOID
+EFIAPI
+InitializeSmmBasePtr (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol (&gEfiSmmBaseProtocolGuid, NULL, (VOID **) &mSmmBaseProtocol);
+ if (EFI_ERROR (Status)) {
+ mSmmBaseProtocol = NULL;
+ }
+}
+
+/**
+ Call back function to publish Hii data
+
+ @param[in] Event - The triggered event.
+ @param[in] Context - Context for this event.
+**/
+VOID
+EFIAPI
+HiiCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+
+#if (EFI_SPECIFICATION_VERSION >= 0x2000A)
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;
+#else
+ EFI_HII_PACKAGES *PackageList;
+#endif
+ EFI_STATUS Status;
+
+ ///
+ /// Initialize strings to HII database
+ ///
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+
+ Status = gBS->LocateProtocol (
+ &gEfiHiiDatabaseProtocolGuid,
+ NULL,
+ &mHiiDatabase
+ );
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ ///
+ /// Create driver handle used by HII database
+ ///
+ Status = CreateHiiDriverHandle (&mDriverHandle);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ ///
+ /// Publish our HII data
+ ///
+ PackageList = PreparePackageList (1, &gProcessorProducerGuid, CpuInitDxeStrings);
+ if (PackageList == NULL) {
+ return;
+ }
+ Status = mHiiDatabase->NewPackageList (
+ mHiiDatabase,
+ PackageList,
+ mDriverHandle,
+ &mStringHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+#else
+ ///
+ /// There should only be one HII protocol
+ ///
+ Status = gBS->LocateProtocol (
+ &gEfiHiiProtocolGuid,
+ NULL,
+ (VOID **) &mHii
+ );
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+ PackageList = PreparePackages (1, &gProcessorProducerGuid, CpuInitDxeStrings);
+ Status = mHii->NewPack (mHii, PackageList, &mStringHandle);
+ FreePool (PackageList);
+#endif
+}
+
+/**
+ Create SMBIOS Table type - FviSmbiosType, when ExitPmAuth event is signaled
+
+ @param[in] Event - A pointer to the Event that triggered the callback.
+ @param[in] Context - A pointer to private data registered with the callback function.
+ **/
+VOID
+InitializeFviDataCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ VOID *ProtocolPointer;
+ UINT32 uCodeRevision;
+
+ Status = gBS->LocateProtocol (&gExitPmAuthProtocolGuid, NULL, &ProtocolPointer);
+ if (EFI_SUCCESS != Status) {
+ return;
+ }
+
+ gBS->CloseEvent (Event);
+
+ if (mPlatformCpu->CpuConfig->FviReport) {
+ InitFviDataHubCbContext (
+ mPlatformCpu->CpuConfig->FviSmbiosType,
+ (UINT8) mCpuFviElements,
+ &mCpuFviVersionData
+ );
+
+ uCodeRevision = GetCpuUcodeRevision ();
+ mCpuFviElementsData[UCODE_VER].Element.Version.MajorVersion = (UINT8) ((uCodeRevision & 0xFF000000) >> 24);
+ mCpuFviElementsData[UCODE_VER].Element.Version.MinorVersion = (UINT8) ((uCodeRevision & 0x00FF0000) >> 16);
+ mCpuFviElementsData[UCODE_VER].Element.Version.Revision = (UINT8) ((uCodeRevision & 0x0000FF00) >> 8);
+ mCpuFviElementsData[UCODE_VER].Element.Version.BuildNum = (UINT16) (uCodeRevision & 0x000000FF);
+
+ CreateRcFviDatahub (&mCpuFviVersionData);
+ }
+ return;
+}
+
+/**
+ Initialize the state information for the CPU Architectural Protocol
+
+ @param[in] ImageHandle - Image handle of the loaded driver
+ @param[in] SystemTable - Pointer to the System Table
+
+ @retval EFI_SUCCESS - thread can be successfully created
+ @retval EFI_OUT_OF_RESOURCES - cannot allocate protocol data structure
+ @retval EFI_DEVICE_ERROR - cannot create the thread
+**/
+EFI_STATUS
+EFIAPI
+InitializeCpu (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE NewHandle1;
+ VOID *Registration;
+
+ ///
+ /// Initialize the Global Descriptor Table
+ ///
+ InitializeSelectors ();
+
+ ///
+ /// Setup Cache attributes and Interrupt Tables
+ ///
+ PrepareMemory ();
+
+ ///
+ /// Initialize Exception Handlers
+ ///
+ InitializeException (&gCpu);
+
+ ///
+ /// Install CPU Architectural Protocol
+ ///
+ NewHandle1 = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &NewHandle1,
+ &gEfiCpuArchProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &gCpu
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Refresh memory space attributes according to MTRRs
+ ///
+ Status = RefreshGcdMemoryAttributes ();
+ mIsFlushingGCD = FALSE;
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ///
+ /// Locate DxeCpuPlatformPolicy protocol instance and assign it to a global variable
+ ///
+ Status = gBS->LocateProtocol (&gDxeCpuPlatformPolicyProtocolGuid, NULL, (VOID **) &mPlatformCpu);
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR,"Failed to locate DxeCpuPlatformPolicy Protocol\n"));
+ return Status;
+ }
+
+ //
+ // Dump Cpu platform policy
+ //
+ CpuDxePolicyDump();
+
+ ///
+ /// Initialize the global SmmBase SWSMI number
+ ///
+ mSmmbaseSwSmiNumber = mPlatformCpu->CpuConfig->SmmbaseSwSmiNumber;
+
+ ///
+ /// Load the microcode if needed
+ ///
+ Status = LoadAllMicrocodeUpdates ();
+
+ Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **) &mMetronome);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+#if (EFI_SPECIFICATION_VERSION >= 0x2000A)
+ EfiLibCreateProtocolNotifyEvent (
+ &gEfiHiiDatabaseProtocolGuid,
+ EFI_TPL_CALLBACK,
+ HiiCallback,
+ NULL,
+ &Registration
+ );
+#else
+ EfiLibCreateProtocolNotifyEvent (
+ &gEfiHiiProtocolGuid,
+ EFI_TPL_CALLBACK,
+ HiiCallback,
+ NULL,
+ &Registration
+ );
+#endif
+
+ ///
+ /// Create an SmmBase protocol call back event to initialize
+ /// Smm Base pointer, during SMM mode
+ ///
+ EfiCreateProtocolNotifyEvent (
+ &gEfiSmmBaseProtocolGuid,
+ TPL_CALLBACK,
+ InitializeSmmBasePtr,
+ NULL,
+ &mSmmBaseRegistration
+ );
+
+ ///
+ /// Initialize MP Support if necessary
+ ///
+ Status = InitializeMpSupport ();
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR,"Failed to initialize MPs\n"));
+ }
+
+ ///
+ /// Create an ExitPmAuth protocol callback event to generate SMBIOS table - FviSmbiosType
+ ///
+ EfiCreateProtocolNotifyEvent (
+ &gExitPmAuthProtocolGuid,
+ EFI_TPL_CALLBACK,
+ InitializeFviDataCallback,
+ NULL,
+ &Registration
+ );
+
+ ///
+ /// Create an ExitPmAuth protocol callback event for PFAT.
+ ///
+ EfiCreateProtocolNotifyEvent (
+ &gExitPmAuthProtocolGuid,
+ EFI_TPL_CALLBACK,
+ InitializePfatToolsIntCallback,
+ NULL,
+ &Registration
+ );
+
+ ///
+ /// Verify if Boot Guard is supported
+ ///
+ if (IsBootGuardSupported()){
+ ///
+ /// Identify if Revocation is requested by Boot Guard ACM
+ ///
+ if (AsmReadMsr64 (MSR_BOOT_GUARD_SACM_INFO) & BIT7) {
+ ///
+ /// Create an ExitPmAuth protocol call back event if one or more of Boot Guard modules are revoked.
+ ///
+ EfiCreateProtocolNotifyEvent (
+ &gExitPmAuthProtocolGuid,
+ TPL_CALLBACK,
+ BootGuardRevocationCallback,
+ NULL,
+ &Registration
+ );
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Returns the actual CPU core frequency in MHz.
+
+ @param[in] Metronome - Metronome protocol
+ @param[in] Frequency - Pointer to the CPU core frequency
+
+ @retval EFI_SUCCESS - If the frequency is returned successfully
+ @retval EFI_INVALID_PARAMETER - If the input parameter is wrong
+**/
+EFI_STATUS
+GetActualFrequency (
+ IN EFI_METRONOME_ARCH_PROTOCOL *Metronome,
+ OUT UINT64 *Frequency
+ )
+{
+ UINT64 BeginValue;
+ UINT64 EndValue;
+ UINT64 TotalValue;
+ UINT32 TickCount;
+ BOOLEAN InterruptState;
+ EFI_STATUS Status;
+
+ if (Metronome == NULL || Frequency == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (mCpuFrequency == 0) {
+ ///
+ /// In order to calculate the actual CPU frequency, we keep track of the CPU Tsc value (which
+ /// increases by 1 for every cycle) for a know period of time. The Metronome is not accurate
+ /// for the 1st tick, so I choose to wait for 1000 ticks, thus the error can be control to be
+ /// lower than 1%.
+ ///
+ TickCount = SAMPLE_TICK_COUNT;
+ CpuGetInterruptState (&gCpu, &InterruptState);
+ if (InterruptState) {
+ DisableInterrupt (&gCpu);
+ }
+ ///
+ /// In DxeCis-0.91 specs.
+ /// Metronome->WaitForTick is possible for interrupt processing,
+ /// or exception processing to interrupt the execution of the WaitForTick() function.
+ /// Depending on the hardware source for the ticks, it is possible for a tick to be missed.
+ /// This function cannot guarantee that ticks will not be missed.
+ ///
+ while (TRUE) {
+ BeginValue = EfiReadTsc ();
+ Status = Metronome->WaitForTick (Metronome, TickCount);
+ EndValue = EfiReadTsc ();
+ if (!EFI_ERROR (Status)) {
+ TotalValue = EndValue - BeginValue;
+ break;
+ }
+ }
+
+ if (InterruptState) {
+ EnableInterrupt (&gCpu);
+ }
+
+ mCpuFrequency = MultU64x32 (TotalValue, 10);
+ mCpuFrequency = DivU64x32 (mCpuFrequency, Metronome->TickPeriod * TickCount);
+ }
+
+ *Frequency = mCpuFrequency;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Dump RC CPU and PPM platform policies
+**/
+VOID
+CpuDxePolicyDump (
+ VOID
+ )
+{
+#ifdef EFI_DEBUG
+ CPU_CONFIG *CpuConfig;
+ POWER_MGMT_CONFIG *PowerMgmtConfig;
+ SECURITY_CONFIG *SecurityConfig;
+
+ CpuConfig = mPlatformCpu->CpuConfig;
+ PowerMgmtConfig = mPlatformCpu->PowerMgmtConfig;
+ SecurityConfig = mPlatformCpu->SecurityConfig;
+ //
+ // Dump Cpu Platform policy
+ //
+ DEBUG ((EFI_D_INFO, "\n------------------------ DXE CpuPlatformPolicy Dump Begin -----------------\n"));
+ //
+ // Cpu config
+ //
+ DEBUG ((EFI_D_INFO, " CPU:: HtState : 0x%X \n", CpuConfig->HtState));
+ DEBUG ((EFI_D_INFO, " CPU:: LimitCpuidMaximumValue : 0x%X\n", CpuConfig->LimitCpuidMaximumValue));
+ DEBUG ((EFI_D_INFO, " CPU:: ExecuteDisableBit : 0x%X\n", CpuConfig->ExecuteDisableBit));
+ DEBUG ((EFI_D_INFO, " CPU:: VmxEnable : 0x%X\n", CpuConfig->VmxEnable));
+ DEBUG ((EFI_D_INFO, " CPU:: SmxEnable : 0x%X\n", CpuConfig->SmxEnable));
+ DEBUG ((EFI_D_INFO, " CPU:: MachineCheckEnable : 0x%X\n", CpuConfig->MachineCheckEnable));
+ DEBUG ((EFI_D_INFO, " CPU:: MonitorMwaitEnable : 0x%X\n", CpuConfig->MonitorMwaitEnable));
+ DEBUG ((EFI_D_INFO, " CPU:: XapicEnable : 0x%X\n", CpuConfig->XapicEnable));
+ DEBUG ((EFI_D_INFO, " CPU:: IsColdReset : 0x%X\n", CpuConfig->IsColdReset));
+ DEBUG ((EFI_D_INFO, " CPU:: MlcStreamerPrefetcher : 0x%X\n", CpuConfig->MlcStreamerPrefetcher));
+ DEBUG ((EFI_D_INFO, " CPU:: EnableDts : 0x%X\n", CpuConfig->EnableDts));
+ DEBUG ((EFI_D_INFO, " CPU:: FviReport : 0x%X\n", CpuConfig->FviReport));
+ DEBUG ((EFI_D_INFO, " CPU:: AesEnable : 0x%X\n", CpuConfig->AesEnable));
+ DEBUG ((EFI_D_INFO, " CPU:: DebugInterfaceEnable : 0x%X\n", CpuConfig->DebugInterfaceEnable));
+ DEBUG ((EFI_D_INFO, " CPU:: DebugInterfaceLockEnable : 0x%X\n", CpuConfig->DebugInterfaceLockEnable));
+ DEBUG ((EFI_D_INFO, " CPU:: ApIdleManner : 0x%X\n", CpuConfig->ApIdleManner));
+ DEBUG ((EFI_D_INFO, " CPU:: ApHandoffManner : 0x%X\n", CpuConfig->ApHandoffManner));
+ DEBUG ((EFI_D_INFO, " CPU:: BspSelection : 0x%X\n", CpuConfig->BspSelection));
+ DEBUG ((EFI_D_INFO, " CPU:: SmmbaseSwSmiNumber : 0x%X\n", CpuConfig->SmmbaseSwSmiNumber));
+ DEBUG ((EFI_D_INFO, " CPU:: FviSmbiosType; : 0x%X\n", CpuConfig->FviSmbiosType));
+ //
+ // SECURITY_CONFIG : TXT_FUNCTION_CONFIG
+ //
+ DEBUG ((EFI_D_INFO, " CPU:: SECURITY_CONFIG:TXT_FUNCTION_CONFIG : ResetAux : 0x%X\n", SecurityConfig->TxtFunctionConfig->ResetAux));
+ DEBUG ((EFI_D_INFO, "\n------------------------ DXE CpuPlatformPolicy Dump End -----------------\n"));
+#endif
+}
+
+/**
+ Initialize the global DataHub pointer
+
+ @param[in] DataHub - Pointer to the DataHub protocol as output
+
+ @retval EFI_SUCCESS - If the DataHub pointer is initialized successfully
+**/
+EFI_STATUS
+InitializeDataHubPtr (
+ OUT EFI_DATA_HUB_PROTOCOL **DataHub
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol (&gEfiDataHubProtocolGuid, NULL, (VOID **) DataHub);
+ return Status;
+}
+
+/**
+ Drop into SMM to register IOTRAP for pfat tools interface
+
+ @param[in] Event - A pointer to the Event that triggered the callback.
+ @param[in] Context - A pointer to private data registered with the callback function.
+**/
+VOID
+InitializePfatToolsIntCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ VOID *ProtocolPointer;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ PFAT_HOB *PfatHobPtr;
+ EFI_GUID PfatHobGuid = PFAT_HOB_GUID;
+
+ Status = gBS->LocateProtocol (&gExitPmAuthProtocolGuid, NULL, &ProtocolPointer);
+ if (EFI_SUCCESS != Status) {
+ return;
+ }
+
+ PfatHobPtr = GetFirstGuidHob (&PfatHobGuid);
+ if (PfatHobPtr != NULL) {
+ BaseAddress = (EFI_PHYSICAL_ADDRESS) PfatHobPtr->PfatToolsIntIoTrapAdd;
+ ///
+ /// IOTRAP TO SMM
+ ///
+ IoRead8 (BaseAddress);
+ }
+ return;
+}
+
+/**
+ Register callback function for Boot Guard revocation flow.
+
+ @param[in] Event - A pointer to the Event that triggered the callback.
+ @param[in] Context - A pointer to private data registered with the callback function.
+**/
+VOID
+EFIAPI
+BootGuardRevocationCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ VOID *ProtocolPointer;
+
+ //
+ // Check whether this is real ExitPmAuth notification, or just a SignalEvent
+ //
+ Status = gBS->LocateProtocol (&gExitPmAuthProtocolGuid, NULL, (VOID **) &ProtocolPointer);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ BootGuardOemRevocationHook();
+
+ //
+ // Closed the event to avoid call twice
+ //
+ gBS->CloseEvent (Event);
+
+ return;
+}
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxe.cif b/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxe.cif
new file mode 100644
index 0000000..f533f7c
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxe.cif
@@ -0,0 +1,46 @@
+<component>
+ name = "CpuInitDxe"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\CpuInit\Dxe"
+ RefName = "CpuInitDxe"
+[files]
+"CacheData.h"
+"CacheData.c"
+"CpuInitDxe.c"
+"CpuInitDxeDbgr.c"
+"CpuInitDxe.h"
+"CpuInitDxeDbgr.h"
+"CpuFvi.c"
+"Exception.h"
+"MachineCheck.c"
+"MachineCheck.h"
+"MemoryAttribute.c"
+"MemoryAttribute.h"
+"Microcode.c"
+"MpCommon.c"
+"MpCommon.h"
+"MpService.c"
+"MpService.h"
+"PiMpService.c"
+"PiMpService.h"
+"MtrrSync.c"
+"Features.c"
+"Features.h"
+"ProcessorData.c"
+"ProcessorData.h"
+"CpuInitDxeStrings.uni"
+"CpuInitDxe.inf"
+"CpuInitDxe.dxs"
+"CpuInitDxe.sdl"
+"CpuInitDxe.mak"
+"x64\Cpu.asm"
+"x64\MpFuncs.asm"
+"x64\MemoryOperation.c"
+"x64\MemoryOperationDbgr.c"
+"x64\Exception.c"
+"x64\MpCpu.c"
+"x64\CpuLib.h"
+"x64\ProcessorDef.h"
+"x64\VirtualMemory.h"
+"x64\MpEqu.inc"
+<endComponent>
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxe.dxs b/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxe.dxs
new file mode 100644
index 0000000..5298ba3
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxe.dxs
@@ -0,0 +1,57 @@
+/** @file
+ This is the Dependency expression for the CPU architectural protocol
+
+@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 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
+
+**/
+
+//
+// Common for R8 and R9 codebase
+//
+#include "AutoGen.h"
+#include "DxeDepex.h"
+
+//
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are both "defined" in R8 codebase;
+// BUILD_WITH_EDKII_GLUE_LIB is defined in Edk-Dev-Snapshot-20070228 and later version
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are "not defined" in R9 codebase.
+//
+#if defined (BUILD_WITH_GLUELIB) || defined (BUILD_WITH_EDKII_GLUE_LIB)
+#include "EfiDepex.h"
+#include EFI_PROTOCOL_DEFINITION (CpuIo)
+#if (EFI_SPECIFICATION_VERSION>=0x2000A)
+#include EFI_PROTOCOL_DEFINITION (HiiDatabase)
+#else
+#include EFI_PROTOCOL_DEFINITION (Hii)
+#endif
+#include EFI_ARCH_PROTOCOL_DEFINITION (Variable)
+#include EFI_ARCH_PROTOCOL_DEFINITION (Metronome)
+#include EFI_PROTOCOL_DEFINITION (CpuPlatformPolicy)
+#endif
+
+DEPENDENCY_START
+ EFI_METRONOME_ARCH_PROTOCOL_GUID AND
+ EFI_CPU_IO_PROTOCOL_GUID AND
+#if (EFI_SPECIFICATION_VERSION>=0x2000A)
+ EFI_HII_DATABASE_PROTOCOL_GUID AND
+#else
+ EFI_HII_PROTOCOL_GUID AND
+#endif
+ EFI_VARIABLE_ARCH_PROTOCOL_GUID AND
+ DXE_CPU_PLATFORM_POLICY_PROTOCOL_GUID
+DEPENDENCY_END
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxe.h b/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxe.h
new file mode 100644
index 0000000..a7be681
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxe.h
@@ -0,0 +1,546 @@
+/** @file
+ Private data structures
+
+@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 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
+
+**/
+#ifndef _CPU_INIT_DXE_H
+#define _CPU_INIT_DXE_H
+
+#include "CpuAccess.h"
+#include "MemoryAttribute.h"
+#include "RcFviDxeLib.h"
+#include "EdkIIGlueBaseLib.h"
+
+#include EFI_PROTOCOL_DEFINITION (CpuPlatformPolicy)
+#include EFI_PROTOCOL_CONSUMER (ExitPmAuth)
+#include EFI_PROTOCOL_DEFINITION (CpuInfo)
+
+#if (EFI_SPECIFICATION_VERSION >= 0x2000A)
+#include "UefiIfrLibrary.h"
+#endif
+
+#define INTERRUPT_VECTOR_NUMBER 256
+#define INTERRUPT_GATE_ATTRIBUTE 0x8e00
+#define NUMBER_OF_MICROCODE_UPDATE 10
+
+extern UINT8 mSmmbaseSwSmiNumber;
+
+#define CPU_FVI_STRING "Reference Code - CPU"
+#define CPU_FVI_SMBIOS_TYPE 0xDD ///< Default value
+#define CPU_FVI_SMBIOS_INSTANCE 0x02
+#define UCODE_FVI_STRING "uCode Version"
+#define UCODE_VERSION \
+ { \
+ 0xFF, 0xFF, 0xFF, 0xFFFF \
+ }
+#define TXT_FVI_STRING "TXT ACM version"
+#define TXT_ACM_MAJOR_VERSION 0x1
+#define TXT_ACM_MINOR_VERSION 0x3
+#define TXT_ACM_REVERSION 0x0
+#define TXT_ACM_BUILD_NUMBER 0x1
+#define TXT_VERSION \
+ { \
+ TXT_ACM_MAJOR_VERSION, TXT_ACM_MINOR_VERSION, TXT_ACM_REVERSION, TXT_ACM_BUILD_NUMBER \
+ }
+enum {
+ CPU_RC_VER= 0,
+ UCODE_VER,
+ TXT_VER
+} CPU_FVI_INDEX;
+
+extern FVI_ELEMENT_AND_FUNCTION mCpuFviElementsData[];
+extern FVI_DATA_HUB_CALLBACK_CONTEXT mCpuFviVersionData;
+extern UINTN mCpuFviElements;
+
+/**
+ Adjust length to a paragraph boundry
+
+ @param[in] MemoryLength - Input memory length.
+
+ @retval Returned Maximum length.
+**/
+UINT64
+Power2MaxMemory (
+ IN UINT64 MemoryLength
+ );
+
+/**
+ Disable cache and its mtrr
+
+ @param[in] OldMtrr - To return the Old MTRR value
+**/
+VOID
+EfiDisableCacheMtrr (
+ IN UINT64 *OldMtrr
+ );
+
+/**
+ Recover cache MTRR
+
+ @param[in] EnableMtrr - Whether to enable the MTRR
+ @param[in] OldMtrr - The saved old MTRR value to restore when not to
+ enable the MTRR
+**/
+VOID
+EfiRecoverCacheMtrr (
+ IN BOOLEAN EnableMtrr,
+ IN UINT64 OldMtrr
+ );
+
+typedef struct _ALIGNED_DWORD {
+ UINT32 High;
+ UINT32 Low;
+} ALIGNED_DWORD;
+
+typedef union _ALIGNED {
+ UINT64 AlignedQword;
+ ALIGNED_DWORD AlignedDword;
+} ALIGNED;
+
+/**
+ Initialize the state information for the CPU Architectural Protocol
+
+ @param[in] ImageHandle - Image handle of the loaded driver
+ @param[in] SystemTable - Pointer to the System Table
+
+ @retval EFI_SUCCESS - thread can be successfully created
+ @retval EFI_OUT_OF_RESOURCES - cannot allocate protocol data structure
+ @retval EFI_DEVICE_ERROR - cannot create the thread
+**/
+EFI_STATUS
+EFIAPI
+InitializeCpu (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Prepare memory for essential system tables.
+
+ @retval EFI_SUCCESS - Memory successfully prepared.
+**/
+EFI_STATUS
+PrepareMemory (
+ VOID
+ );
+
+/**
+ Flush CPU data cache. If the instruction cache is fully coherent
+ with all DMA operations then function can just return EFI_SUCCESS.
+
+ @param[in] This - Protocol instance structure
+ @param[in] Start - Physical address to start flushing from.
+ @param[in] Length - Number of bytes to flush. Round up to chipset granularity.
+ @param[in] FlushType - Specifies the type of flush operation to perform.
+
+ @retval EFI_SUCCESS - If cache was flushed
+ @exception EFI_UNSUPPORTED - If flush type is not supported.
+ @retval EFI_DEVICE_ERROR - If requested range could not be flushed.
+**/
+EFI_STATUS
+EFIAPI
+FlushCpuDataCache (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length,
+ IN EFI_CPU_FLUSH_TYPE FlushType
+ );
+
+/**
+ Enables CPU interrupts.
+
+ @param[in] This - Protocol instance structure
+
+ @retval EFI_SUCCESS - If interrupts were enabled in the CPU
+ @retval EFI_DEVICE_ERROR - If interrupts could not be enabled on the CPU.
+**/
+EFI_STATUS
+EFIAPI
+EnableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ );
+
+/**
+ Disables CPU interrupts.
+
+ @param[in] This - Protocol instance structure
+
+ @retval EFI_SUCCESS - If interrupts were disabled in the CPU.
+ @retval EFI_DEVICE_ERROR - If interrupts could not be disabled on the CPU.
+**/
+EFI_STATUS
+EFIAPI
+DisableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ );
+
+/**
+ Return the state of interrupts.
+
+ @param[in] This - Protocol instance structure
+ @param[in] State - Pointer to the CPU's current interrupt state
+
+ @retval EFI_SUCCESS - If interrupts were disabled in the CPU.
+ @retval EFI_INVALID_PARAMETER - State is NULL.
+**/
+EFI_STATUS
+EFIAPI
+CpuGetInterruptState (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ OUT BOOLEAN *State
+ );
+
+/**
+ Generates an INIT to the CPU
+
+ @param[in] This - Protocol instance structure
+ @param[in] InitType - Type of CPU INIT to perform
+
+ @retval EFI_SUCCESS - If CPU INIT occurred. This value should never be seen.
+ @retval EFI_DEVICE_ERROR - If CPU INIT failed.
+ @exception EFI_UNSUPPORTED - Requested type of CPU INIT not supported.
+**/
+EFI_STATUS
+EFIAPI
+Init (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_CPU_INIT_TYPE InitType
+ );
+
+/**
+ Registers a function to be called from the CPU interrupt handler.
+
+ @param[in] This - Protocol instance structure
+ @param[in] InterruptType - Defines which interrupt to hook.
+ IA-32 valid range is 0x00 through 0xFF
+ @param[in] InterruptHandler - A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER
+ that is called when a processor interrupt occurs.
+ A null pointer is an error condition.
+
+ @retval EFI_SUCCESS - If handler installed or uninstalled.
+ @retval EFI_ALREADY_STARTED - InterruptHandler is not NULL, and a handler for
+ InterruptType was previously installed
+ @retval EFI_INVALID_PARAMETER - InterruptHandler is NULL, and a handler for
+ InterruptType was not previously installed.
+ @exception EFI_UNSUPPORTED - The interrupt specified by InterruptType is not supported.
+**/
+EFI_STATUS
+EFIAPI
+RegisterInterruptHandler (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ );
+
+/**
+ Returns a timer value from one of the CPU's internal timers. There is no
+ inherent time interval between ticks but is a function of the CPU frequency.
+
+ @param[in] This - Protocol instance structure.
+ @param[in] TimerIndex - Specifies which CPU timer is requested.
+ @param[in] TimerValue - Pointer to the returned timer value.
+ @param[in] TimerPeriod - A pointer to the amount of time that passes in femtoseconds (10-15) for each
+ increment of TimerValue. If TimerValue does not increment at a predictable
+ rate, then 0 is returned. The amount of time that has passed between two calls to
+ GetTimerValue() can be calculated with the formula
+ (TimerValue2 - TimerValue1) * TimerPeriod. This parameter is optional and may be NULL.
+
+ @retval EFI_SUCCESS - If the CPU timer count was returned.
+ @exception EFI_UNSUPPORTED - If the CPU does not have any readable timers.
+ @retval EFI_DEVICE_ERROR - If an error occurred while reading the timer.
+ @retval EFI_INVALID_PARAMETER - TimerIndex is not valid or TimerValue is NULL.
+**/
+EFI_STATUS
+EFIAPI
+GetTimerValue (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ );
+
+/**
+ Set memory cacheability attributes for given range of memeory
+
+ @param[in] This - Protocol instance structure
+ @param[in] BaseAddress - Specifies the start address of the memory range
+ @param[in] Length - Specifies the length of the memory range
+ @param[in] Attributes - The memory cacheability for the memory range
+
+ @retval EFI_SUCCESS - If the cacheability of that memory range is set successfully
+ @exception EFI_UNSUPPORTED - If the desired operation cannot be done
+ @retval EFI_INVALID_PARAMETER - The input parameter is not correct, such as Length = 0
+**/
+EFI_STATUS
+EFIAPI
+SetMemoryAttributes (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ );
+
+/**
+ Init Global Descriptor table
+**/
+VOID
+InitializeSelectors (
+ VOID
+ );
+
+typedef struct {
+ VOID *Start;
+ UINTN Size;
+ UINTN FixOffset;
+} INTERRUPT_HANDLER_TEMPLATE_MAP;
+
+typedef union {
+ EFI_CPU_DATA_RECORD *DataRecord;
+ UINT8 *Raw;
+} EFI_CPU_DATA_RECORD_BUFFER;
+
+///
+/// This constant defines the maximum length of the CPU brand string. According to the
+/// IA manual, the brand string is in EAX through EDX (thus 16 bytes) after executing
+/// the CPUID instructions with EAX as 80000002, 80000003, 80000004.
+///
+#define MAXIMUM_CPU_BRAND_STRING_LENGTH 48
+
+typedef struct {
+ BOOLEAN StringValid;
+ CHAR16 BrandString[MAXIMUM_CPU_BRAND_STRING_LENGTH + 1];
+ EFI_PROCESSOR_VERSION_DATA StringRef;
+} PROCESSOR_VERSION_INFORMATION;
+
+///
+/// The constant defines how many times the Cpuid instruction should be executed
+/// in order to get all the cache information. For Pentium 4 processor, 1 is enough
+///
+#define CPU_CPUID_EXECTION_COUNT 2
+
+typedef struct {
+ UINT64 IntendCoreFrequency;
+ UINT64 IntendFsbFrequency;
+ PROCESSOR_VERSION_INFORMATION Version;
+ EFI_PROCESSOR_MANUFACTURER_DATA Manufacturer;
+ EFI_PROCESSOR_ID_DATA CpuidData;
+ EFI_PROCESSOR_FAMILY_DATA Family;
+ INT16 Voltage;
+ EFI_PROCESSOR_APIC_BASE_ADDRESS_DATA ApicBase;
+ EFI_PROCESSOR_APIC_ID_DATA ApicID;
+ EFI_PROCESSOR_APIC_VERSION_NUMBER_DATA ApicVersion;
+ UINT32 MicrocodeRevision;
+ EFI_PROCESSOR_STATUS_DATA Status; ///< Need to update this field before report
+ CPU_PHYSICAL_LOCATION Location;
+ EFI_MP_HEALTH_FLAGS Health;
+ EFI_CPUID_REGISTER CacheInformation[CPU_CPUID_EXECTION_COUNT];
+} CPU_DATA_FOR_DATAHUB;
+
+///
+/// Type, FamilyId and Model values for the different processors
+/// [0:7] - Model
+/// [8:23] - FamilyId
+/// [24:31] - Type
+///
+#define RESERVED 0x00
+
+/**
+ This will locate a processor microcode and if it finds a newer revision, it will
+ load it to the processor.
+
+ @param[in] MicrocodePointerBuffer - The Array of pointers which each points to 1 microcode update binary (in memory)
+ @param[in] FailedRevision - The microcode revision that fails to be loaded
+
+ @retval EFI_SUCCESS - A new microcode update is loaded
+ @retval Other - Due to some reason, no new microcode update is loaded
+**/
+EFI_STATUS
+InitializeMicrocode (
+ IN EFI_CPU_MICROCODE_HEADER **MicrocodePointerBuffer,
+ OUT UINT32 *FailedRevision
+ );
+
+/**
+ To indicate the first microcode load is done
+**/
+VOID
+McuFirstLoadDone (
+ VOID
+ );
+
+/**
+ Initializes MP support in the system.
+
+ @retval EFI_SUCCESS - Multiple processors are initialized successfully.
+ @retval EFI_NOT_FOUND - The ACPI variable is not found in S3 boot path.
+ @retval EFI_OUT_OF_RESOURCES - No enough resoruces (such as out of memory).
+**/
+EFI_STATUS
+InitializeMpSupport (
+ VOID
+ );
+
+/**
+ Save the MTRR registers to global variables
+**/
+VOID
+ReadMtrrRegisters (
+ VOID
+ );
+
+/**
+ Synch up the MTRR values for all processors
+**/
+VOID
+EFIAPI
+MpMtrrSynchUp (
+ IN VOID *Buffer
+ );
+
+/**
+ Copy Global MTRR data to S3
+**/
+VOID
+SaveBspMtrrForS3 (
+ VOID
+ );
+
+/**
+ Load all microcode updates to memory. Since in S3 resume boot path, CPUs should be
+ patched again, these microcode updates are copied to OS reserved memory.
+
+ @retval EFI_SUCCESS - All microcode updates are loaded to memory successfully
+ @retval EFI_OUT_OF_RESOURCES - Not enough memory to accomodate all the microcode updates
+**/
+EFI_STATUS
+LoadAllMicrocodeUpdates (
+ VOID
+ );
+
+/**
+ Returns the actual CPU core frequency in MHz.
+
+ @param[in] Metronome - Metronome protocol
+ @param[in] Frequency - Pointer to the CPU core frequency
+
+ @retval EFI_SUCCESS - If the frequency is returned successfully
+ @retval EFI_INVALID_PARAMETER - If the input parameter is wrong
+**/
+EFI_STATUS
+GetActualFrequency (
+ IN EFI_METRONOME_ARCH_PROTOCOL *Metronome,
+ OUT UINT64 *Frequency
+ );
+
+/**
+ Dump RC CPU and PPM platform policies
+**/
+VOID
+CpuDxePolicyDump (
+ VOID
+ );
+
+/**
+ Initialize the global DataHub pointer
+
+ @param[in] DataHub - Pointer to the DataHub protocol as output
+
+ @retval EFI_SUCCESS - If the DataHub pointer is initialized successfully
+**/
+EFI_STATUS
+InitializeDataHubPtr (
+ OUT EFI_DATA_HUB_PROTOCOL **DataHub
+ );
+
+/**
+ Check if loading microcode update fails, if so, report proper status code
+
+ @param[in] CpuNumber - The CPU number
+ @param[in] Status - The return value of InitializeMicrocode()
+ @param[in] FailedRevision - The revision of the microcode update that failed to be loaded
+
+ @retval EFI_SUCCESS - The status is check and proper status code is reported
+**/
+EFI_STATUS
+CheckMicrocodeUpdate (
+ IN UINTN CpuNumber,
+ IN EFI_STATUS Status,
+ IN UINT32 FailedRevision
+ );
+
+/**
+ Enable Cpu Interrupt
+**/
+VOID
+CpuEnableInterrupt (
+ VOID
+ );
+
+/**
+ Disable Cpu Interrupt
+**/
+VOID
+CpuDisableInterrupt (
+ VOID
+ );
+
+/**
+ Get code segment
+
+ @retval Code segmnet value
+**/
+UINT16
+GetCodeSegment (
+ VOID
+ );
+
+/**
+ Initialize Cpu float point unit
+**/
+VOID
+CpuInitFloatPointUnit (
+ VOID
+ );
+
+/**
+ Drop into SMM to register IOTRAP handler for pfat tools interface
+
+ @param[in] Event - A pointer to the Event that triggered the callback.
+ @param[in] Context - A pointer to private data registered with the callback function.
+**/
+VOID
+InitializePfatToolsIntCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ Register callback function for Boot Guard revocation flow.
+
+ @param[in] Event - A pointer to the Event that triggered the callback.
+ @param[in] Context - A pointer to private data registered with the callback function.
+**/
+VOID
+EFIAPI
+BootGuardRevocationCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+#endif
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxe.inf b/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxe.inf
new file mode 100644
index 0000000..bd66192
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxe.inf
@@ -0,0 +1,171 @@
+## @file
+# Component description file for MP Cpu module.
+#
+#@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 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
+#
+
+[defines]
+BASE_NAME = CpuInitDxe
+FILE_GUID = 62D171CB-78CD-4480-8678-C6A2A797A8DE
+COMPONENT_TYPE = BS_DRIVER
+
+[sources.ia32]
+
+[sources.x64]
+ x64/Cpu.asm
+ x64/MpFuncs.asm
+ x64/MemoryOperation.c
+ x64/Exception.c
+ x64/MpCpu.c
+ x64/CpuLib.h
+ x64/ProcessorDef.h
+ x64/VirtualMemory.h
+
+[sources.common]
+ CacheData.h
+ CacheData.c
+ CpuInitDxe.c
+ CpuInitDxe.h
+ Exception.h
+ MachineCheck.c
+ MachineCheck.h
+ MemoryAttribute.c
+ MemoryAttribute.h
+ Microcode.c
+ MpCommon.c
+ MpCommon.h
+ MpService.c
+ MpService.h
+ PiMpService.c
+ PiMpService.h
+ MtrrSync.c
+ Features.c
+ Features.h
+ ProcessorData.c
+ ProcessorData.h
+ CpuInitDxeStrings.uni
+ CpuFvi.c
+
+#
+# Edk II Glue Driver Entry Point
+#
+ EdkIIGlueDxeDriverEntryPoint.c
+
+[includes.common]
+ $(DEST_DIR)
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/FrameWork
+ $(EDK_SOURCE)/Foundation/FrameWork/Include
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/Pei/Include
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Cpu/Pentium/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/CpuInit/Dxe
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/CpuInit/Dxe/x64
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include/Library
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library
+
+#
+# if (EFI_SPECIFICATION_VERSION < 0x0002000A), use EfiIfrSupportLib
+# if (EFI_SPECIFICATION_VERSION >= 0x0002000A), use UefiEfiIfrSupportLib
+#
+# $(EDK_SOURCE)/Foundation/Library/Dxe/EfiIfrSupportLib
+ $(EDK_SOURCE)/Foundation/Library/Dxe/UefiEfiIfrSupportLib
+
+#
+# Edk II Glue Library, some hearder are included by R9 header so have to include
+#
+ $(EFI_SOURCE)
+ $(EFI_SOURCE)/Framework
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include/Library
+#
+# Typically the sample code referenced will be available in the code base already
+# So keep this include at the end to defer to the source base definition
+# and only use the sample code definition if source base does not include these files.
+#
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/SampleCode
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/SampleCode/Include
+
+[libraries.common]
+ EfiGuidLib
+ EdkFrameworkProtocolLib
+ EdkProtocolLib
+ EdkIIGlueBaseIoLibIntrinsic
+ EdkIIGlueBaseLib
+ EdkIIGlueBaseMemoryLib
+ EdkIIGlueDxeReportStatusCodeLib
+ EdkIIGlueDxeServicesTableLib
+ EdkIIGlueDxeDebugLibReportStatusCode
+ EdkIIGlueUefiBootServicesTableLib
+ EdkIIGlueUefiRuntimeServicesTableLib
+ EdkIIGlueUefiLib
+ EdkIIGlueBasePciLibPciExpress
+ EdkIIGlueDxeMemoryAllocationLib
+ EdkIIGlueDxeHobLib
+ EdkIIGlueHiiLib
+ EdkIIGlueBaseTimerLibLocalApic
+
+#
+# if (EFI_SPECIFICATION_VERSION < 0x0002000A), use EfiIfrSupportLib
+# if (EFI_SPECIFICATION_VERSION >= 0x0002000A), use UefiEfiIfrSupportLib, EfiDriverLib
+#
+# EfiIfrSupportLib
+ EfiDriverLib
+ UefiEfiIfrSupportLib
+ CpuProtocolLib
+ CpuGuidLib
+ CpuIA32Lib
+ RcFviDxeLib
+ CpuPlatformLib
+ BootGuardLib
+ BootGuardRevocationLib
+
+[nmake.common]
+ IMAGE_ENTRY_POINT=_ModuleEntryPoint
+ DPX_SOURCE=CpuInitDxe.dxs
+#
+# Module Entry Point
+#
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=InitializeCpu
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ -D __EDKII_GLUE_BASE_LIB__ \
+ -D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ -D __EDKII_GLUE_DXE_REPORT_STATUS_CODE_LIB__ \
+ -D __EDKII_GLUE_DXE_SERVICES_TABLE_LIB__
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ -D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_UEFI_LIB__ \
+ -D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ \
+ -D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \
+ -D __EDKII_GLUE_DXE_HOB_LIB__
+
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxe.mak b/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxe.mak
new file mode 100644
index 0000000..f3d5922
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxe.mak
@@ -0,0 +1,140 @@
+# MAK file for the eModule:PowerManagement
+
+EDK : CpuInitDxe
+
+BUILD_CpuInitDxe_DIR = $(BUILD_DIR)\$(CpuInitDxe_DIR)
+
+$(BUILD_DIR)\CpuInitDxe.mak : $(CpuInitDxe_DIR)\CpuInitDxe.cif $(BUILD_RULES)
+ $(CIF2MAK) $(CpuInitDxe_DIR)\CpuInitDxe.cif $(CIF2MAK_DEFAULTS)
+
+CpuInitDxe : $(BUILD_DIR)\CpuInitDxe.MAK CpuInitDxeBin
+
+CpuInitDxe_OBJECTS = \
+ $(BUILD_CpuInitDxe_DIR)\CacheData.obj \
+ $(BUILD_CpuInitDxe_DIR)\CpuFvi.obj \
+ $(BUILD_CpuInitDxe_DIR)\MachineCheck.obj \
+ $(BUILD_CpuInitDxe_DIR)\MemoryAttribute.obj \
+ $(BUILD_CpuInitDxe_DIR)\Microcode.obj \
+ $(BUILD_CpuInitDxe_DIR)\MpCommon.obj \
+ $(BUILD_CpuInitDxe_DIR)\MpService.obj \
+ $(BUILD_CpuInitDxe_DIR)\PiMpService.obj \
+ $(BUILD_CpuInitDxe_DIR)\MtrrSync.obj \
+ $(BUILD_CpuInitDxe_DIR)\Features.obj \
+ $(BUILD_CpuInitDxe_DIR)\ProcessorData.obj \
+ $(BUILD_CpuInitDxe_DIR)\x64\Cpu.obj \
+ $(BUILD_CpuInitDxe_DIR)\x64\MpFuncs.obj \
+ $(BUILD_CpuInitDxe_DIR)\x64\Exception.obj \
+ $(BUILD_CpuInitDxe_DIR)\x64\MpCpu.obj \
+!IFDEF PeiDebugger_SUPPORT
+!IF $(PeiDebugger_SUPPORT)
+ $(BUILD_CpuInitDxe_DIR)\CpuInitDxeDbgr.obj \
+ $(BUILD_CpuInitDxe_DIR)\x64\MemoryOperationDbgr.obj \
+!ELSE
+ $(BUILD_CpuInitDxe_DIR)\CpuInitDxe.obj \
+ $(BUILD_CpuInitDxe_DIR)\x64\MemoryOperation.obj \
+!ENDIF
+!ELSE
+ $(BUILD_CpuInitDxe_DIR)\CpuInitDxe.obj \
+ $(BUILD_CpuInitDxe_DIR)\x64\MemoryOperation.obj \
+!ENDIF
+ $(BUILD_DIR)\CpuInitDxeStrings.obj \
+
+CpuInitDxe_MY_INCLUDES= \
+ $(EdkIIGlueLib_INCLUDES)\
+ $(EDK_INCLUDES)\
+ $(PROJECT_CPU_INCLUDES)\
+ $(INTEL_PCH_INCLUDES)\
+ /I$(PROJECT_CPU_ROOT)\CpuInit\Dxe\
+ /I$(PROJECT_CPU_ROOT)\CpuInit\Dxe\x64\
+ /I$(PROJECT_CPU_ROOT)\CpuSmm\Include\
+ /I$(UefiEfiIfrSupportLib_DIR)\
+ /I$(PROJECT_CPU_ROOT)\
+ /I$(PROJECT_CPU_ROOT)\Include\
+ /IBoard\EM\Platform\SMBIOSUpdateData
+
+CpuInitDxe_DEFINES = $(MY_DEFINES)\
+ /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=InitializeCpu"\
+ /D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ /D __EDKII_GLUE_BASE_LIB__ \
+ /D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ /D __EDKII_GLUE_DXE_REPORT_STATUS_CODE_LIB__ \
+ /D __EDKII_GLUE_DXE_SERVICES_TABLE_LIB__ \
+ /D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ /D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \
+ /D __EDKII_GLUE_UEFI_LIB__ \
+ /D __EDKII_GLUE_UEFI_DEVICE_PATH_LIB__ \
+ /D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ \
+ /D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \
+ /D __EDKII_GLUE_DXE_HOB_LIB__ \
+ /D REQUEST_EBDA_SIZE="$(REQUEST_EBDA_SIZE)" \
+!IFDEF AMI_PEI_DEBUG_SUPPORT
+!IF $(AMI_PEI_DEBUG_SUPPORT)
+ /D __AMI_PEI_DEBUG_SUPPORT__
+!ENDIF
+!ENDIF
+!IF $(CPU_MODULE_CREATE_SMBIOS_TABLES)
+ /D__CREATE_CPU_SMBIOS__
+!ENDIF
+
+CpuInitDxe_LIBS =\
+ $(EFIGUIDLIB)\
+ $(EDKFRAMEWORKPROTOCOLLIB)\
+ $(EDKPROTOCOLLIB)\
+ $(EdkIIGlueBaseIoLibIntrinsic_LIB)\
+ $(EdkIIGlueBaseLib_LIB)\
+ $(EdkIIGlueBaseMemoryLib_LIB)\
+ $(EdkIIGlueDxeReportStatusCodeLib_LIB)\
+ $(EdkIIGlueDxeServicesTableLib_LIB)\
+ $(EdkIIGlueDxeDebugLibReportStatusCode_LIB)\
+ $(EdkIIGlueUefiBootServicesTableLib_LIB)\
+ $(EdkIIGlueUefiLib_LIB)\
+ $(EdkIIGlueBasePciLibPciExpress_LIB)\
+ $(EdkIIGlueDxeMemoryAllocationLib_LIB)\
+ $(EdkIIGlueBaseTimerLibLocalApic_LIB)\
+ $(EdkIIGlueDxeHobLib_LIB)\
+ $(EdkIIGlueHiiLib_LIB)\
+ $(EFIDRIVERLIB)\
+ $(UEFIEFIIFRSUPPORTLIB)\
+ $(CpuProtocolLib_LIB)\
+ $(CpuGuidLib_LIB)\
+ $(CPUIA32LIB)\
+ $(CpuPlatformLib_LIB)\
+ $(PchPlatformDxeLib_LIB)\
+ $(RcFviDxeLib_LIB)\
+ $(BootGuardRevocationLib_LIB)\
+ $(BootGuardLib_LIB)
+
+
+CpuInitDxeBin : $(CpuInitDxe_LIBS)
+ $(CC) $(CFLAGS) /Fo$(BUILD_DIR)\ $(BUILD_DIR)\CpuInitDxeStrings.c
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\CpuInitDxe.mak all\
+ NAME=CpuInitDxe\
+ MAKEFILE=$(BUILD_DIR)\CpuInitDxe.mak \
+ "MY_INCLUDES=$(CpuInitDxe_MY_INCLUDES)" \
+ "MY_DEFINES=$(CpuInitDxe_DEFINES)"\
+ OBJECTS="$(CpuInitDxe_OBJECTS)" \
+ GUID=62D171CB-78CD-4480-8678-C6A2A797A8DE\
+ ENTRY_POINT=_ModuleEntryPoint \
+ TYPE=RT_DRIVER \
+ EDKIIModule=DXEDRIVER\
+ DEPEX1=$(CpuInitDxe_DIR)\CpuInitDxe.DXS \
+ DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX \
+ COMPRESS=1
+
+#---------------------------------------------------------------------------
+# Create Cpu SDB data
+#---------------------------------------------------------------------------
+SetupSdbs : CpuDxeSDB
+
+CpuDxeSDB : $(BUILD_DIR)\CpuInitDxe.mak
+ $(MAKE) /$(MAKEFLAGS) $(BUILD_DEFAULTS)\
+ /f $(BUILD_DIR)\CpuInitDxe.mak all\
+ TYPE=SDB NAME=CpuInitDxe
+ $(STRGATHER) -dump -lang $(SUPPORTED_LANGUAGES: = -lang )\
+ -db $(BUILD_DIR)\CpuInitDxe.sdb\
+ -oh $(BUILD_DIR)\CpuInitDxeStrDefs.h\
+ -bn CpuInitDxeStrings\
+ -oc $(BUILD_DIR)\CpuInitDxeStrings.c
+# $(CC) $(CFLAGS) /Fo$(BUILD_DIR)\ $(BUILD_DIR)\CpuInitDxeStrings.c
+
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxe.sdl b/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxe.sdl
new file mode 100644
index 0000000..e50eae9
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxe.sdl
@@ -0,0 +1,45 @@
+TOKEN
+ Name = "CpuInitDxe_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable Cpu Pei init support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+End
+
+TOKEN
+ Name = "REQUEST_EBDA_SIZE"
+ Value = "0x1000"
+ Help = "Default value 0x1000. If we need to use EBDA, please change the token value to 0x2000. For example, Using mini-pcie card."
+ TokenType = Integer
+ TargetMAK = Yes
+End
+
+PATH
+ Name = "CpuInitDxe_DIR"
+End
+
+MODULE
+ Help = "Includes CpuPeiInit.mak to Project"
+ File = "CpuInitDxe.mak"
+End
+
+ELINK
+ Name = "CpuInitDxe_INCLUDES"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "/I$(CpuInitDxe_DIR)"
+ Parent = "CpuInitDxe_INCLUDES"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\CpuInitDxe.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End
+
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxeDbgr.c b/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxeDbgr.c
new file mode 100644
index 0000000..308329e
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxeDbgr.c
@@ -0,0 +1,1112 @@
+/** @file
+ Cpu driver, which initializes CPU and implements CPU Architecture
+ Protocol as defined in Framework specification.
+
+@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 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
+
+**/
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "CpuInitDxeDbgr.h"
+#include "ProcessorData.h"
+#include "CacheData.h"
+#include "Exception.h"
+#include "PfatDefinitions.h"
+#include "BootGuardLibrary.h"
+#include "BootGuardRevocationLib.h"
+//(AMI_CHG+)>
+#if defined(AMI_PEI_DEBUG_SUPPORT) && AMI_PEI_DEBUG_SUPPORT
+EFI_GUID gAmiDebuggerCpuProtocolGuid = AMI_DEBUGGER_CPU_PROTOCOL_GUID;
+AMI_DEBUGGER_CPU_PROTOCOL *mAmiDebuggerCpuProtocol;
+VOID* AptioInterruptHandlerHalt;
+UINT32 AptioInterruptHandlerHalt1;
+VOID
+EFIAPI CommonExceptionHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ );
+#endif
+//<(AMI_CHG+)
+
+#define SAMPLE_TICK_COUNT 1000
+
+#endif
+
+extern UINT64 mValidMtrrAddressMask;
+extern UINT64 mValidMtrrBitsMask;
+extern EFI_CPU_MICROCODE_HEADER **mMicrocodePointerBuffer;
+extern UINT8 CpuInitDxeStrings[];
+
+#if (EFI_SPECIFICATION_VERSION >= 0x2000A)
+EFI_HANDLE mDriverHandle;
+EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;
+#else
+EFI_HII_PROTOCOL *mHii;
+#endif
+EFI_SMM_BASE_PROTOCOL *mSmmBaseProtocol = NULL;
+VOID *mSmmBaseRegistration;
+EFI_METRONOME_ARCH_PROTOCOL *mMetronome;
+DXE_CPU_PLATFORM_POLICY_PROTOCOL *mPlatformCpu = NULL;
+EFI_HII_HANDLE mStringHandle;
+BOOLEAN mIsFlushingGCD = TRUE;
+UINT8 mSmmbaseSwSmiNumber;
+BOOLEAN mVariableMtrrChanged;
+BOOLEAN mFixedMtrrChanged;
+UINT64 mCpuFrequency = 0;
+
+EFI_EVENT gReadyToBootEvent;
+EFI_CPU_INTERRUPT_HANDLER mExternalVectorTable[0x100];
+BOOLEAN mInterruptState = FALSE;
+
+///
+/// The Cpu Architectural Protocol that this Driver produces
+///
+EFI_CPU_ARCH_PROTOCOL gCpu = {
+ FlushCpuDataCache,
+ EnableInterrupt,
+ DisableInterrupt,
+ CpuGetInterruptState,
+ Init,
+ RegisterInterruptHandler,
+ GetTimerValue,
+ SetMemoryAttributes,
+ 1, ///< NumberOfTimers
+ 4, ///< DmaBufferAlignment
+};
+
+/**
+ Decide if the CPU is executing in SMM mode
+
+ @retval TRUE - The CPU is executing in SMM mode
+ @retval FALSE - The CPU is not executing in SMM mode
+**/
+BOOLEAN
+ExecutionInSmm (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN InSmm;
+
+ if (mSmmBaseProtocol == NULL) {
+ return FALSE;
+ }
+
+ Status = mSmmBaseProtocol->InSmm (mSmmBaseProtocol, &InSmm);
+ ASSERT_EFI_ERROR (Status);
+ return InSmm;
+}
+
+/**
+ Flush CPU data cache. If the instruction cache is fully coherent
+ with all DMA operations then function can just return EFI_SUCCESS.
+
+ @param[in] This - Protocol instance structure
+ @param[in] Start - Physical address to start flushing from.
+ @param[in] Length - Number of bytes to flush. Round up to chipset
+ granularity.
+ @param[in] FlushType - Specifies the type of flush operation to perform.
+
+ @retval EFI_SUCCESS - If cache was flushed
+ @exception EFI_UNSUPPORTED - If flush type is not supported.
+ @retval EFI_DEVICE_ERROR - If requested range could not be flushed.
+**/
+EFI_STATUS
+EFIAPI
+FlushCpuDataCache (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length,
+ IN EFI_CPU_FLUSH_TYPE FlushType
+ )
+{
+ if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {
+ AsmWbinvd ();
+ return EFI_SUCCESS;
+ } else if (FlushType == EfiCpuFlushTypeInvalidate) {
+ EfiInvd ();
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+}
+
+/**
+ Enables CPU interrupts.
+
+ @param[in] This - Protocol instance structure
+
+ @retval EFI_SUCCESS - If interrupts were enabled in the CPU
+ @retval EFI_DEVICE_ERROR - If interrupts could not be enabled on the CPU.
+**/
+EFI_STATUS
+EFIAPI
+EnableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ )
+{
+ if (!ExecutionInSmm ()) {
+ CpuEnableInterrupt ();
+ }
+
+ mInterruptState = TRUE;
+ return EFI_SUCCESS;
+}
+
+/**
+ Disables CPU interrupts.
+
+ @param[in] This - Protocol instance structure
+
+ @retval EFI_SUCCESS - If interrupts were disabled in the CPU.
+**/
+EFI_STATUS
+EFIAPI
+DisableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ )
+{
+ CpuDisableInterrupt ();
+
+ mInterruptState = FALSE;
+ return EFI_SUCCESS;
+}
+
+/**
+ Return the state of interrupts.
+
+ @param[in] This - Protocol instance structure
+ @param[in] State - Pointer to the CPU's current interrupt state
+
+ @retval EFI_SUCCESS - If interrupts were disabled in the CPU.
+ @retval EFI_INVALID_PARAMETER - State is NULL.
+**/
+EFI_STATUS
+EFIAPI
+CpuGetInterruptState (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ OUT BOOLEAN *State
+ )
+{
+ if (State == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *State = mInterruptState;
+ return EFI_SUCCESS;
+}
+
+/**
+ Generates an INIT to the CPU
+
+ @param[in] This - Protocol instance structure
+ @param[in] InitType - Type of CPU INIT to perform
+
+ @retval EFI_SUCCESS - If CPU INIT occurred. This value should never be seen
+ @retval EFI_DEVICE_ERROR - If CPU INIT failed.
+ @exception EFI_UNSUPPORTED - Requested type of CPU INIT not supported.
+**/
+EFI_STATUS
+EFIAPI
+Init (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_CPU_INIT_TYPE InitType
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Registers a function to be called from the CPU interrupt handler.
+
+ @param[in] This - Protocol instance structure
+ @param[in] InterruptType - Defines which interrupt to hook.
+ IA-32 valid range is 0x00 through 0xFF
+ @param[in] InterruptHandler - A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER
+ that is called when a processor interrupt occurs.
+ A null pointer is an error condition.
+
+ @retval EFI_SUCCESS - If handler installed or uninstalled.
+ @retval EFI_ALREADY_STARTED - InterruptHandler is not NULL, and a handler for
+ InterruptType was previously installed
+ @retval EFI_INVALID_PARAMETER - InterruptHandler is NULL, and a handler for
+ InterruptType was not previously installed.
+ @exception EFI_UNSUPPORTED - The interrupt specified by InterruptType is not supported.
+**/
+EFI_STATUS
+EFIAPI
+RegisterInterruptHandler (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ )
+{
+//(AMI_CHG+)>
+#if defined(AMI_PEI_DEBUG_SUPPORT) && AMI_PEI_DEBUG_SUPPORT
+ EFI_STATUS Status;
+#endif
+//<(AMI_CHG+)
+
+ if (InterruptType < 0 || InterruptType > 0xff) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (InterruptHandler == NULL && mExternalVectorTable[InterruptType] == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (InterruptHandler != NULL && mExternalVectorTable[InterruptType] != NULL) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ mExternalVectorTable[InterruptType] = InterruptHandler;
+
+//AMI_CHG>
+#if defined(AMI_PEI_DEBUG_SUPPORT) && AMI_PEI_DEBUG_SUPPORT
+ if ((UINT32) InterruptHandler == (UINT32)CommonExceptionHandler)
+ Status = mAmiDebuggerCpuProtocol->DebuggerIsDebuggerIrqHadler(InterruptType,AptioInterruptHandlerHalt);
+ else
+ Status = mAmiDebuggerCpuProtocol->DebuggerIsDebuggerIrqHadler(InterruptType,InterruptHandler);
+#endif
+//<AMI_CHG
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+GetTimerValue (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ )
+/**
+ Returns a timer value from one of the CPU's internal timers. There is no
+ inherent time interval between ticks but is a function of the CPU frequency.
+
+ @param[in] This - Protocol instance structure.
+ @param[in] TimerIndex - Specifies which CPU timer is requested.
+ @param[in] TimerValue - Pointer to the returned timer value.
+ @param[in] TimerPeriod - A pointer to the amount of time that passes in femtoseconds (10-15) for each
+ increment of TimerValue. If TimerValue does not increment at a predictable
+ rate, then 0 is returned. The amount of time that has passed between two calls to
+ GetTimerValue() can be calculated with the formula
+ (TimerValue2 - TimerValue1) * TimerPeriod. This parameter is optional and may be NULL.
+
+ @retval EFI_SUCCESS - If the CPU timer count was returned.
+ @exception EFI_UNSUPPORTED - If the CPU does not have any readable timers.
+ @retval EFI_DEVICE_ERROR - If an error occurred while reading the timer.
+ @retval EFI_INVALID_PARAMETER - TimerIndex is not valid or TimerValue is NULL.
+**/
+{
+ UINT64 Actual;
+
+ if (TimerValue == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (TimerIndex != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *TimerValue = EfiReadTsc ();
+
+ if (TimerPeriod != NULL) {
+ GetActualFrequency (mMetronome, &Actual);
+ *TimerPeriod = DivU64x32 (1000000000, (UINT32) Actual);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set memory cacheability attributes for given range of memeory
+
+ @param[in] This - Protocol instance structure
+ @param[in] BaseAddress - Specifies the start address of the memory range
+ @param[in] Length - Specifies the length of the memory range
+ @param[in] Attributes - The memory cacheability for the memory range
+
+ @retval EFI_SUCCESS - If the cacheability of that memory range is set successfully
+ @exception EFI_UNSUPPORTED - If the desired operation cannot be done
+ @retval EFI_INVALID_PARAMETER - The input parameter is not correct, such as Length = 0
+**/
+EFI_STATUS
+EFIAPI
+SetMemoryAttributes (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ )
+{
+ EFI_STATUS Status;
+ UINT64 TempQword;
+ UINT32 MsrNum;
+ UINTN MtrrNumber;
+ BOOLEAN Positive;
+ BOOLEAN OverLap;
+#define SKIP_ALIGN_CHECK 0
+#if SKIP_ALIGN_CHECK
+ UINT32 Remainder;
+#endif
+ EFI_MP_SERVICES_PROTOCOL *MpService;
+ EFI_STATUS Status1;
+ UINT32 VariableMtrrLimit;
+
+ mFixedMtrrChanged = FALSE;
+ mVariableMtrrChanged = FALSE;
+
+ VariableMtrrLimit = (UINT32) (AsmReadMsr64 (IA32_MTRR_CAP) & B_IA32_MTRR_VARIABLE_SUPPORT);
+
+ if (mIsFlushingGCD) {
+ return EFI_SUCCESS;
+ }
+
+ TempQword = 0;
+
+ ///
+ /// Check for invalid parameter
+ ///
+ if (Length == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((BaseAddress &~mValidMtrrAddressMask) != 0 || (Length &~mValidMtrrAddressMask) != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ switch (Attributes) {
+ case EFI_MEMORY_UC:
+ Attributes = CACHE_UNCACHEABLE;
+ break;
+
+ case EFI_MEMORY_WC:
+ Attributes = CACHE_WRITECOMBINING;
+ break;
+
+ case EFI_MEMORY_WT:
+ Attributes = CACHE_WRITETHROUGH;
+ break;
+
+ case EFI_MEMORY_WP:
+ Attributes = CACHE_WRITEPROTECTED;
+ break;
+
+ case EFI_MEMORY_WB:
+ Attributes = CACHE_WRITEBACK;
+ break;
+
+ default:
+ return EFI_UNSUPPORTED;
+ }
+
+ ///
+ /// Check if Fixed MTRR
+ ///
+ Status = EFI_SUCCESS;
+ while ((BaseAddress < (1 << 20)) && (Length > 0) && Status == EFI_SUCCESS) {
+ Status = CalculateFixedMtrr (Attributes, &BaseAddress, &Length);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ if (mFixedMtrrChanged) {
+ ProgramFixedMtrr ();
+ }
+
+ if (Length == 0) {
+ ///
+ /// Just Fixed MTRR. NO need to go through Variable MTRR
+ ///
+ goto Done;
+ }
+
+ ///
+ /// since mem below 1m will be override by fixed mtrr, we can set it to 0 to save mtrr.
+ ///
+ if (BaseAddress == 0x100000) {
+ BaseAddress = 0;
+ Length += 0x100000;
+ }
+
+ ///
+ /// Check memory base address alignment
+ ///
+#if SKIP_ALIGN_CHECK
+ DivU64x32Remainder (BaseAddress, (UINT32) Power2MaxMemory (LShiftU64 (Length, 1)), &Remainder);
+ if (Remainder != 0) {
+ DivU64x32Remainder (BaseAddress, (UINT32) Power2MaxMemory (Length), &Remainder);
+ if (Remainder != 0) {
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+ }
+#endif
+
+ ///
+ /// Check overlap
+ ///
+ GetMemoryAttribute ();
+ OverLap = CheckMemoryAttributeOverlap (BaseAddress, BaseAddress + Length - 1);
+ if (OverLap) {
+ Status = CombineMemoryAttribute (Attributes, &BaseAddress, &Length);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ if (Length == 0) {
+ ///
+ /// combine successfully
+ ///
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+ } else {
+ if (Attributes == CACHE_UNCACHEABLE) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+ }
+
+ ///
+ /// Program Variable MTRRs
+ ///
+ if (mUsedMtrr >= VariableMtrrLimit) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ ///
+ /// Find first unused MTRR
+ ///
+ for (MsrNum = CACHE_VARIABLE_MTRR_BASE; MsrNum < (CACHE_VARIABLE_MTRR_BASE + VariableMtrrLimit * 2 - 1); MsrNum += 2) {
+ if ((AsmReadMsr64 (MsrNum + 1) & B_CACHE_MTRR_VALID) == 0) {
+ break;
+ }
+ }
+
+ TempQword = Length;
+ if (TempQword == Power2MaxMemory (TempQword)) {
+ ProgramVariableMtrr (
+ MsrNum,
+ BaseAddress,
+ Length,
+ Attributes
+ );
+ } else {
+ GetDirection (TempQword, &MtrrNumber, &Positive);
+ if ((mUsedMtrr + MtrrNumber) > VariableMtrrLimit) {
+ goto Done;
+ }
+ if (!Positive) {
+ Length = Power2MaxMemory (LShiftU64 (TempQword, 1));
+ ProgramVariableMtrr (
+ MsrNum,
+ BaseAddress,
+ Length,
+ Attributes
+ );
+ BaseAddress += TempQword;
+ TempQword = Length - TempQword;
+ Attributes = CACHE_UNCACHEABLE;
+ }
+ do {
+ ///
+ /// Find unused MTRR
+ ///
+ for (; MsrNum < (CACHE_VARIABLE_MTRR_BASE + VariableMtrrLimit * 2 - 1); MsrNum += 2) {
+ if ((AsmReadMsr64 (MsrNum + 1) & B_CACHE_MTRR_VALID) == 0) {
+ break;
+ }
+ }
+ Length = Power2MaxMemory (TempQword);
+ ProgramVariableMtrr (
+ MsrNum,
+ BaseAddress,
+ Length,
+ Attributes
+ );
+ BaseAddress += Length;
+ TempQword -= Length;
+ } while (TempQword);
+ }
+
+Done:
+ Status1 = gBS->LocateProtocol (
+ &gEfiMpServiceProtocolGuid,
+ NULL,
+ (VOID **) &MpService
+ );
+
+ if (!EFI_ERROR (Status1)) {
+ if (mVariableMtrrChanged || mFixedMtrrChanged) {
+ ///
+ /// PERF_START (NULL, L"CacheSync", NULL, 0);
+ ///
+ ReadMtrrRegisters ();
+ Status1 = MpService->StartupAllAPs (
+ MpService,
+ MpMtrrSynchUp,
+ FALSE,
+ NULL,
+ 0,
+ NULL,
+ NULL
+ );
+ ///
+ /// PERF_END (NULL, L"CacheSync", NULL, 0);
+ ///
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Initialize the SmmBase pointer when SmmBase protocol get installed
+
+ @param[in] Event - Event whose notification function is being invoked.
+ @param[in] Context - Pointer to the notification functions context, which is implementation dependent.
+**/
+VOID
+EFIAPI
+InitializeSmmBasePtr (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol (&gEfiSmmBaseProtocolGuid, NULL, (VOID **) &mSmmBaseProtocol);
+ if (EFI_ERROR (Status)) {
+ mSmmBaseProtocol = NULL;
+ }
+}
+
+/**
+ Call back function to publish Hii data
+
+ @param[in] Event - The triggered event.
+ @param[in] Context - Context for this event.
+**/
+VOID
+EFIAPI
+HiiCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+
+#if (EFI_SPECIFICATION_VERSION >= 0x2000A)
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;
+#else
+ EFI_HII_PACKAGES *PackageList;
+#endif
+ EFI_STATUS Status;
+
+ ///
+ /// Initialize strings to HII database
+ ///
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+
+ Status = gBS->LocateProtocol (
+ &gEfiHiiDatabaseProtocolGuid,
+ NULL,
+ &mHiiDatabase
+ );
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ ///
+ /// Create driver handle used by HII database
+ ///
+ Status = CreateHiiDriverHandle (&mDriverHandle);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ ///
+ /// Publish our HII data
+ ///
+ PackageList = PreparePackageList (1, &gProcessorProducerGuid, CpuInitDxeStrings);
+ if (PackageList == NULL) {
+ return;
+ }
+ Status = mHiiDatabase->NewPackageList (
+ mHiiDatabase,
+ PackageList,
+ mDriverHandle,
+ &mStringHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+#else
+ ///
+ /// There should only be one HII protocol
+ ///
+ Status = gBS->LocateProtocol (
+ &gEfiHiiProtocolGuid,
+ NULL,
+ (VOID **) &mHii
+ );
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+ PackageList = PreparePackages (1, &gProcessorProducerGuid, CpuInitDxeStrings);
+ Status = mHii->NewPack (mHii, PackageList, &mStringHandle);
+ FreePool (PackageList);
+#endif
+}
+
+/**
+ Create SMBIOS Table type - FviSmbiosType, when ExitPmAuth event is signaled
+
+ @param[in] Event - A pointer to the Event that triggered the callback.
+ @param[in] Context - A pointer to private data registered with the callback function.
+ **/
+VOID
+InitializeFviDataCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ VOID *ProtocolPointer;
+ UINT32 uCodeRevision;
+
+ Status = gBS->LocateProtocol (&gExitPmAuthProtocolGuid, NULL, &ProtocolPointer);
+ if (EFI_SUCCESS != Status) {
+ return;
+ }
+
+ gBS->CloseEvent (Event);
+
+ if (mPlatformCpu->CpuConfig->FviReport) {
+ InitFviDataHubCbContext (
+ mPlatformCpu->CpuConfig->FviSmbiosType,
+ (UINT8) mCpuFviElements,
+ &mCpuFviVersionData
+ );
+
+ uCodeRevision = GetCpuUcodeRevision ();
+ mCpuFviElementsData[UCODE_VER].Element.Version.MajorVersion = (UINT8) ((uCodeRevision & 0xFF000000) >> 24);
+ mCpuFviElementsData[UCODE_VER].Element.Version.MinorVersion = (UINT8) ((uCodeRevision & 0x00FF0000) >> 16);
+ mCpuFviElementsData[UCODE_VER].Element.Version.Revision = (UINT8) ((uCodeRevision & 0x0000FF00) >> 8);
+ mCpuFviElementsData[UCODE_VER].Element.Version.BuildNum = (UINT16) (uCodeRevision & 0x000000FF);
+
+ CreateRcFviDatahub (&mCpuFviVersionData);
+ }
+ return;
+}
+
+/**
+ Initialize the state information for the CPU Architectural Protocol
+
+ @param[in] ImageHandle - Image handle of the loaded driver
+ @param[in] SystemTable - Pointer to the System Table
+
+ @retval EFI_SUCCESS - thread can be successfully created
+ @retval EFI_OUT_OF_RESOURCES - cannot allocate protocol data structure
+ @retval EFI_DEVICE_ERROR - cannot create the thread
+**/
+EFI_STATUS
+EFIAPI
+InitializeCpu (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE NewHandle1;
+ VOID *Registration;
+
+ ///
+ /// Initialize the Global Descriptor Table
+ ///
+//(AMI_CHG+)>
+#if defined(AMI_PEI_DEBUG_SUPPORT) && AMI_PEI_DEBUG_SUPPORT
+ Status = gBS->LocateProtocol(
+ &gAmiDebuggerCpuProtocolGuid,
+ NULL,
+ &mAmiDebuggerCpuProtocol
+ );
+
+ if (!EFI_ERROR(Status)){
+ Status = mAmiDebuggerCpuProtocol->
+ DebuggerGetAptioIntHandler((VOID*)&AptioInterruptHandlerHalt1);
+
+ (UINT32)AptioInterruptHandlerHalt = AptioInterruptHandlerHalt1;
+
+ Status = mAmiDebuggerCpuProtocol->DebuggerSetupExceptionHandler();
+ }
+#endif
+
+ InitializeSelectors ();
+
+ ///
+ /// Initialize Exception Handlers
+ ///
+ InitializeException (&gCpu);
+
+ ///
+ /// Setup Cache attributes and Interrupt Tables
+ ///
+ PrepareMemory ();
+
+//<(AMI_CHG+)
+
+ ///
+ /// Install CPU Architectural Protocol
+ ///
+ NewHandle1 = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &NewHandle1,
+ &gEfiCpuArchProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &gCpu
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Refresh memory space attributes according to MTRRs
+ ///
+ Status = RefreshGcdMemoryAttributes ();
+ mIsFlushingGCD = FALSE;
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ///
+ /// Locate DxeCpuPlatformPolicy protocol instance and assign it to a global variable
+ ///
+ Status = gBS->LocateProtocol (&gDxeCpuPlatformPolicyProtocolGuid, NULL, (VOID **) &mPlatformCpu);
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR,"Failed to locate DxeCpuPlatformPolicy Protocol\n"));
+ return Status;
+ }
+
+ //
+ // Dump Cpu platform policy
+ //
+ CpuDxePolicyDump();
+
+ ///
+ /// Initialize the global SmmBase SWSMI number
+ ///
+ mSmmbaseSwSmiNumber = mPlatformCpu->CpuConfig->SmmbaseSwSmiNumber;
+
+ ///
+ /// Load the microcode if needed
+ ///
+ Status = LoadAllMicrocodeUpdates ();
+
+ Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **) &mMetronome);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+#if (EFI_SPECIFICATION_VERSION >= 0x2000A)
+ EfiLibCreateProtocolNotifyEvent (
+ &gEfiHiiDatabaseProtocolGuid,
+ EFI_TPL_CALLBACK,
+ HiiCallback,
+ NULL,
+ &Registration
+ );
+#else
+ EfiLibCreateProtocolNotifyEvent (
+ &gEfiHiiProtocolGuid,
+ EFI_TPL_CALLBACK,
+ HiiCallback,
+ NULL,
+ &Registration
+ );
+#endif
+
+ ///
+ /// Create an SmmBase protocol call back event to initialize
+ /// Smm Base pointer, during SMM mode
+ ///
+ EfiCreateProtocolNotifyEvent (
+ &gEfiSmmBaseProtocolGuid,
+ TPL_CALLBACK,
+ InitializeSmmBasePtr,
+ NULL,
+ &mSmmBaseRegistration
+ );
+
+ ///
+ /// Initialize MP Support if necessary
+ ///
+ Status = InitializeMpSupport ();
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR,"Failed to initialize MPs\n"));
+ }
+
+ ///
+ /// Create an ExitPmAuth protocol callback event to generate SMBIOS table - FviSmbiosType
+ ///
+ EfiCreateProtocolNotifyEvent (
+ &gExitPmAuthProtocolGuid,
+ EFI_TPL_CALLBACK,
+ InitializeFviDataCallback,
+ NULL,
+ &Registration
+ );
+
+ ///
+ /// Create an ExitPmAuth protocol callback event for PFAT.
+ ///
+ EfiCreateProtocolNotifyEvent (
+ &gExitPmAuthProtocolGuid,
+ EFI_TPL_CALLBACK,
+ InitializePfatToolsIntCallback,
+ NULL,
+ &Registration
+ );
+
+ ///
+ /// Verify if Boot Guard is supported
+ ///
+ if (IsBootGuardSupported()){
+ ///
+ /// Identify if Revocation is requested by Boot Guard ACM
+ ///
+ if (AsmReadMsr64 (MSR_BOOT_GUARD_SACM_INFO) & BIT7) {
+ ///
+ /// Create an ExitPmAuth protocol call back event if one or more of Boot Guard modules are revoked.
+ ///
+ EfiCreateProtocolNotifyEvent (
+ &gExitPmAuthProtocolGuid,
+ TPL_CALLBACK,
+ BootGuardRevocationCallback,
+ NULL,
+ &Registration
+ );
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Returns the actual CPU core frequency in MHz.
+
+ @param[in] Metronome - Metronome protocol
+ @param[in] Frequency - Pointer to the CPU core frequency
+
+ @retval EFI_SUCCESS - If the frequency is returned successfully
+ @retval EFI_INVALID_PARAMETER - If the input parameter is wrong
+**/
+EFI_STATUS
+GetActualFrequency (
+ IN EFI_METRONOME_ARCH_PROTOCOL *Metronome,
+ OUT UINT64 *Frequency
+ )
+{
+ UINT64 BeginValue;
+ UINT64 EndValue;
+ UINT64 TotalValue;
+ UINT32 TickCount;
+ BOOLEAN InterruptState;
+ EFI_STATUS Status;
+
+ if (Metronome == NULL || Frequency == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (mCpuFrequency == 0) {
+ ///
+ /// In order to calculate the actual CPU frequency, we keep track of the CPU Tsc value (which
+ /// increases by 1 for every cycle) for a know period of time. The Metronome is not accurate
+ /// for the 1st tick, so I choose to wait for 1000 ticks, thus the error can be control to be
+ /// lower than 1%.
+ ///
+ TickCount = SAMPLE_TICK_COUNT;
+ CpuGetInterruptState (&gCpu, &InterruptState);
+ if (InterruptState) {
+ DisableInterrupt (&gCpu);
+ }
+ ///
+ /// In DxeCis-0.91 specs.
+ /// Metronome->WaitForTick is possible for interrupt processing,
+ /// or exception processing to interrupt the execution of the WaitForTick() function.
+ /// Depending on the hardware source for the ticks, it is possible for a tick to be missed.
+ /// This function cannot guarantee that ticks will not be missed.
+ ///
+ while (TRUE) {
+ BeginValue = EfiReadTsc ();
+ Status = Metronome->WaitForTick (Metronome, TickCount);
+ EndValue = EfiReadTsc ();
+ if (!EFI_ERROR (Status)) {
+ TotalValue = EndValue - BeginValue;
+ break;
+ }
+ }
+
+ if (InterruptState) {
+ EnableInterrupt (&gCpu);
+ }
+
+ mCpuFrequency = MultU64x32 (TotalValue, 10);
+ mCpuFrequency = DivU64x32 (mCpuFrequency, Metronome->TickPeriod * TickCount);
+ }
+
+ *Frequency = mCpuFrequency;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Dump RC CPU and PPM platform policies
+**/
+VOID
+CpuDxePolicyDump (
+ VOID
+ )
+{
+#ifdef EFI_DEBUG
+ CPU_CONFIG *CpuConfig;
+ POWER_MGMT_CONFIG *PowerMgmtConfig;
+ SECURITY_CONFIG *SecurityConfig;
+
+ CpuConfig = mPlatformCpu->CpuConfig;
+ PowerMgmtConfig = mPlatformCpu->PowerMgmtConfig;
+ SecurityConfig = mPlatformCpu->SecurityConfig;
+ //
+ // Dump Cpu Platform policy
+ //
+ DEBUG ((EFI_D_INFO, "\n------------------------ DXE CpuPlatformPolicy Dump Begin -----------------\n"));
+ //
+ // Cpu config
+ //
+ DEBUG ((EFI_D_INFO, " CPU:: HtState : 0x%X \n", CpuConfig->HtState));
+ DEBUG ((EFI_D_INFO, " CPU:: LimitCpuidMaximumValue : 0x%X\n", CpuConfig->LimitCpuidMaximumValue));
+ DEBUG ((EFI_D_INFO, " CPU:: ExecuteDisableBit : 0x%X\n", CpuConfig->ExecuteDisableBit));
+ DEBUG ((EFI_D_INFO, " CPU:: VmxEnable : 0x%X\n", CpuConfig->VmxEnable));
+ DEBUG ((EFI_D_INFO, " CPU:: SmxEnable : 0x%X\n", CpuConfig->SmxEnable));
+ DEBUG ((EFI_D_INFO, " CPU:: MachineCheckEnable : 0x%X\n", CpuConfig->MachineCheckEnable));
+ DEBUG ((EFI_D_INFO, " CPU:: MonitorMwaitEnable : 0x%X\n", CpuConfig->MonitorMwaitEnable));
+ DEBUG ((EFI_D_INFO, " CPU:: XapicEnable : 0x%X\n", CpuConfig->XapicEnable));
+ DEBUG ((EFI_D_INFO, " CPU:: IsColdReset : 0x%X\n", CpuConfig->IsColdReset));
+ DEBUG ((EFI_D_INFO, " CPU:: MlcStreamerPrefetcher : 0x%X\n", CpuConfig->MlcStreamerPrefetcher));
+ DEBUG ((EFI_D_INFO, " CPU:: EnableDts : 0x%X\n", CpuConfig->EnableDts));
+ DEBUG ((EFI_D_INFO, " CPU:: FviReport : 0x%X\n", CpuConfig->FviReport));
+ DEBUG ((EFI_D_INFO, " CPU:: AesEnable : 0x%X\n", CpuConfig->AesEnable));
+ DEBUG ((EFI_D_INFO, " CPU:: DebugInterfaceEnable : 0x%X\n", CpuConfig->DebugInterfaceEnable));
+ DEBUG ((EFI_D_INFO, " CPU:: DebugInterfaceLockEnable : 0x%X\n", CpuConfig->DebugInterfaceLockEnable));
+ DEBUG ((EFI_D_INFO, " CPU:: ApIdleManner : 0x%X\n", CpuConfig->ApIdleManner));
+ DEBUG ((EFI_D_INFO, " CPU:: ApHandoffManner : 0x%X\n", CpuConfig->ApHandoffManner));
+ DEBUG ((EFI_D_INFO, " CPU:: BspSelection : 0x%X\n", CpuConfig->BspSelection));
+ DEBUG ((EFI_D_INFO, " CPU:: SmmbaseSwSmiNumber : 0x%X\n", CpuConfig->SmmbaseSwSmiNumber));
+ DEBUG ((EFI_D_INFO, " CPU:: FviSmbiosType; : 0x%X\n", CpuConfig->FviSmbiosType));
+ //
+ // SECURITY_CONFIG : TXT_FUNCTION_CONFIG
+ //
+ DEBUG ((EFI_D_INFO, " CPU:: SECURITY_CONFIG:TXT_FUNCTION_CONFIG : ResetAux : 0x%X\n", SecurityConfig->TxtFunctionConfig->ResetAux));
+ DEBUG ((EFI_D_INFO, "\n------------------------ DXE CpuPlatformPolicy Dump End -----------------\n"));
+#endif
+}
+
+/**
+ Initialize the global DataHub pointer
+
+ @param[in] DataHub - Pointer to the DataHub protocol as output
+
+ @retval EFI_SUCCESS - If the DataHub pointer is initialized successfully
+**/
+EFI_STATUS
+InitializeDataHubPtr (
+ OUT EFI_DATA_HUB_PROTOCOL **DataHub
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol (&gEfiDataHubProtocolGuid, NULL, (VOID **) DataHub);
+ return Status;
+}
+
+/**
+ Drop into SMM to register IOTRAP for pfat tools interface
+
+ @param[in] Event - A pointer to the Event that triggered the callback.
+ @param[in] Context - A pointer to private data registered with the callback function.
+**/
+VOID
+InitializePfatToolsIntCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ VOID *ProtocolPointer;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ PFAT_HOB *PfatHobPtr;
+ EFI_GUID PfatHobGuid = PFAT_HOB_GUID;
+
+ Status = gBS->LocateProtocol (&gExitPmAuthProtocolGuid, NULL, &ProtocolPointer);
+ if (EFI_SUCCESS != Status) {
+ return;
+ }
+
+ PfatHobPtr = GetFirstGuidHob (&PfatHobGuid);
+ if (PfatHobPtr != NULL) {
+ BaseAddress = (EFI_PHYSICAL_ADDRESS) PfatHobPtr->PfatToolsIntIoTrapAdd;
+ ///
+ /// IOTRAP TO SMM
+ ///
+ IoRead8 (BaseAddress);
+ }
+ return;
+}
+
+/**
+ Register callback function for Boot Guard revocation flow.
+
+ @param[in] Event - A pointer to the Event that triggered the callback.
+ @param[in] Context - A pointer to private data registered with the callback function.
+**/
+VOID
+EFIAPI
+BootGuardRevocationCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ VOID *ProtocolPointer;
+
+ //
+ // Check whether this is real ExitPmAuth notification, or just a SignalEvent
+ //
+ Status = gBS->LocateProtocol (&gExitPmAuthProtocolGuid, NULL, (VOID **) &ProtocolPointer);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ BootGuardOemRevocationHook();
+
+ //
+ // Closed the event to avoid call twice
+ //
+ gBS->CloseEvent (Event);
+
+ return;
+}
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxeDbgr.h b/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxeDbgr.h
new file mode 100644
index 0000000..86316bb
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxeDbgr.h
@@ -0,0 +1,602 @@
+/** @file
+ Private data structures
+
+@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 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
+
+**/
+#ifndef _CPU_INIT_DXE_H
+#define _CPU_INIT_DXE_H
+
+#include "CpuAccess.h"
+#include "MemoryAttribute.h"
+#include "RcFviDxeLib.h"
+#include "EdkIIGlueBaseLib.h"
+
+#include EFI_PROTOCOL_DEFINITION (CpuPlatformPolicy)
+#include EFI_PROTOCOL_CONSUMER (ExitPmAuth)
+#include EFI_PROTOCOL_DEFINITION (CpuInfo)
+
+#if (EFI_SPECIFICATION_VERSION >= 0x2000A)
+#include "UefiIfrLibrary.h"
+#endif
+
+#define INTERRUPT_VECTOR_NUMBER 256
+#define INTERRUPT_GATE_ATTRIBUTE 0x8e00
+#define NUMBER_OF_MICROCODE_UPDATE 10
+
+extern UINT8 mSmmbaseSwSmiNumber;
+
+//(AMI_CHG+)
+#if defined(AMI_PEI_DEBUG_SUPPORT) && AMI_PEI_DEBUG_SUPPORT
+
+#define AMI_DEBUGGER_CPU_PROTOCOL_GUID \
+ { 0xab21acc3, 0xba33, 0xee2c, 0x66, 0xbc, 0x12, 0x56, 0x77, 0x11, 0x1a, 0xb2 }
+
+
+typedef struct _AMI_DEBUGGER_CPU_PROTOCOL AMI_DEBUGGER_CPU_PROTOCOL;
+
+#pragma pack(1)
+
+typedef struct {
+ UINT16 Offset15To0;
+ UINT16 SegmentSelector;
+ UINT16 Attributes;
+ UINT16 Offset31To16;
+ UINT32 Offset63To32;
+ UINT32 Reserved;
+} DEBUGGER_INTERRUPT_GATE_DESCRIPTOR;
+
+#pragma pack()
+
+typedef
+EFI_STATUS
+(EFIAPI *DEBUGGER_GET_APTIO_INT_HANDLER) (
+ IN OUT UINT32* InterruptHandlerHaltAddr
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *DEBUGGER_FIXUP_PEI_EXCEPTION_HANDLER) (
+ IN DEBUGGER_INTERRUPT_GATE_DESCRIPTOR* IdtEntry,
+ IN UINT32 i
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *DEBUGGER_SETUP_EXCEPTION_HANDLER) (VOID);
+
+typedef
+EFI_STATUS
+(EFIAPI *DEBUGGER_IS_DEBUGGER_IRQ_HANDLER) (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ );
+
+typedef struct _AMI_DEBUGGER_CPU_PROTOCOL {
+ DEBUGGER_GET_APTIO_INT_HANDLER DebuggerGetAptioIntHandler;
+ DEBUGGER_FIXUP_PEI_EXCEPTION_HANDLER DebuggerFixUpPEIExceptionHandlers;
+ DEBUGGER_SETUP_EXCEPTION_HANDLER DebuggerSetupExceptionHandler;
+ DEBUGGER_IS_DEBUGGER_IRQ_HANDLER DebuggerIsDebuggerIrqHadler;
+};
+
+#endif
+//<(AMI_CHG+)
+
+#define CPU_FVI_STRING "Reference Code - CPU"
+#define CPU_FVI_SMBIOS_TYPE 0xDD ///< Default value
+#define CPU_FVI_SMBIOS_INSTANCE 0x02
+#define UCODE_FVI_STRING "uCode Version"
+#define UCODE_VERSION \
+ { \
+ 0xFF, 0xFF, 0xFF, 0xFFFF \
+ }
+#define TXT_FVI_STRING "TXT ACM version"
+#define TXT_ACM_MAJOR_VERSION 0x1
+#define TXT_ACM_MINOR_VERSION 0x0
+#define TXT_ACM_REVERSION 0x0
+#define TXT_ACM_BUILD_NUMBER 0x0
+#define TXT_VERSION \
+ { \
+ TXT_ACM_MAJOR_VERSION, TXT_ACM_MINOR_VERSION, TXT_ACM_REVERSION, TXT_ACM_BUILD_NUMBER \
+ }
+enum {
+ CPU_RC_VER= 0,
+ UCODE_VER,
+ TXT_VER
+} CPU_FVI_INDEX;
+
+extern FVI_ELEMENT_AND_FUNCTION mCpuFviElementsData[];
+extern FVI_DATA_HUB_CALLBACK_CONTEXT mCpuFviVersionData;
+extern UINTN mCpuFviElements;
+
+/**
+ Adjust length to a paragraph boundry
+
+ @param[in] MemoryLength - Input memory length.
+
+ @retval Returned Maximum length.
+**/
+UINT64
+Power2MaxMemory (
+ IN UINT64 MemoryLength
+ );
+
+/**
+ Disable cache and its mtrr
+
+ @param[in] OldMtrr - To return the Old MTRR value
+**/
+VOID
+EfiDisableCacheMtrr (
+ IN UINT64 *OldMtrr
+ );
+
+/**
+ Recover cache MTRR
+
+ @param[in] EnableMtrr - Whether to enable the MTRR
+ @param[in] OldMtrr - The saved old MTRR value to restore when not to
+ enable the MTRR
+**/
+VOID
+EfiRecoverCacheMtrr (
+ IN BOOLEAN EnableMtrr,
+ IN UINT64 OldMtrr
+ );
+
+typedef struct _ALIGNED_DWORD {
+ UINT32 High;
+ UINT32 Low;
+} ALIGNED_DWORD;
+
+typedef union _ALIGNED {
+ UINT64 AlignedQword;
+ ALIGNED_DWORD AlignedDword;
+} ALIGNED;
+
+/**
+ Initialize the state information for the CPU Architectural Protocol
+
+ @param[in] ImageHandle - Image handle of the loaded driver
+ @param[in] SystemTable - Pointer to the System Table
+
+ @retval EFI_SUCCESS - thread can be successfully created
+ @retval EFI_OUT_OF_RESOURCES - cannot allocate protocol data structure
+ @retval EFI_DEVICE_ERROR - cannot create the thread
+**/
+EFI_STATUS
+EFIAPI
+InitializeCpu (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Prepare memory for essential system tables.
+
+ @retval EFI_SUCCESS - Memory successfully prepared.
+**/
+EFI_STATUS
+PrepareMemory (
+ VOID
+ );
+
+/**
+ Flush CPU data cache. If the instruction cache is fully coherent
+ with all DMA operations then function can just return EFI_SUCCESS.
+
+ @param[in] This - Protocol instance structure
+ @param[in] Start - Physical address to start flushing from.
+ @param[in] Length - Number of bytes to flush. Round up to chipset granularity.
+ @param[in] FlushType - Specifies the type of flush operation to perform.
+
+ @retval EFI_SUCCESS - If cache was flushed
+ @exception EFI_UNSUPPORTED - If flush type is not supported.
+ @retval EFI_DEVICE_ERROR - If requested range could not be flushed.
+**/
+EFI_STATUS
+EFIAPI
+FlushCpuDataCache (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length,
+ IN EFI_CPU_FLUSH_TYPE FlushType
+ );
+
+/**
+ Enables CPU interrupts.
+
+ @param[in] This - Protocol instance structure
+
+ @retval EFI_SUCCESS - If interrupts were enabled in the CPU
+ @retval EFI_DEVICE_ERROR - If interrupts could not be enabled on the CPU.
+**/
+EFI_STATUS
+EFIAPI
+EnableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ );
+
+/**
+ Disables CPU interrupts.
+
+ @param[in] This - Protocol instance structure
+
+ @retval EFI_SUCCESS - If interrupts were disabled in the CPU.
+ @retval EFI_DEVICE_ERROR - If interrupts could not be disabled on the CPU.
+**/
+EFI_STATUS
+EFIAPI
+DisableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ );
+
+/**
+ Return the state of interrupts.
+
+ @param[in] This - Protocol instance structure
+ @param[in] State - Pointer to the CPU's current interrupt state
+
+ @retval EFI_SUCCESS - If interrupts were disabled in the CPU.
+ @retval EFI_INVALID_PARAMETER - State is NULL.
+**/
+EFI_STATUS
+EFIAPI
+CpuGetInterruptState (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ OUT BOOLEAN *State
+ );
+
+/**
+ Generates an INIT to the CPU
+
+ @param[in] This - Protocol instance structure
+ @param[in] InitType - Type of CPU INIT to perform
+
+ @retval EFI_SUCCESS - If CPU INIT occurred. This value should never be seen.
+ @retval EFI_DEVICE_ERROR - If CPU INIT failed.
+ @exception EFI_UNSUPPORTED - Requested type of CPU INIT not supported.
+**/
+EFI_STATUS
+EFIAPI
+Init (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_CPU_INIT_TYPE InitType
+ );
+
+/**
+ Registers a function to be called from the CPU interrupt handler.
+
+ @param[in] This - Protocol instance structure
+ @param[in] InterruptType - Defines which interrupt to hook.
+ IA-32 valid range is 0x00 through 0xFF
+ @param[in] InterruptHandler - A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER
+ that is called when a processor interrupt occurs.
+ A null pointer is an error condition.
+
+ @retval EFI_SUCCESS - If handler installed or uninstalled.
+ @retval EFI_ALREADY_STARTED - InterruptHandler is not NULL, and a handler for
+ InterruptType was previously installed
+ @retval EFI_INVALID_PARAMETER - InterruptHandler is NULL, and a handler for
+ InterruptType was not previously installed.
+ @exception EFI_UNSUPPORTED - The interrupt specified by InterruptType is not supported.
+**/
+EFI_STATUS
+EFIAPI
+RegisterInterruptHandler (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ );
+
+/**
+ Returns a timer value from one of the CPU's internal timers. There is no
+ inherent time interval between ticks but is a function of the CPU frequency.
+
+ @param[in] This - Protocol instance structure.
+ @param[in] TimerIndex - Specifies which CPU timer is requested.
+ @param[in] TimerValue - Pointer to the returned timer value.
+ @param[in] TimerPeriod - A pointer to the amount of time that passes in femtoseconds (10-15) for each
+ increment of TimerValue. If TimerValue does not increment at a predictable
+ rate, then 0 is returned. The amount of time that has passed between two calls to
+ GetTimerValue() can be calculated with the formula
+ (TimerValue2 - TimerValue1) * TimerPeriod. This parameter is optional and may be NULL.
+
+ @retval EFI_SUCCESS - If the CPU timer count was returned.
+ @exception EFI_UNSUPPORTED - If the CPU does not have any readable timers.
+ @retval EFI_DEVICE_ERROR - If an error occurred while reading the timer.
+ @retval EFI_INVALID_PARAMETER - TimerIndex is not valid or TimerValue is NULL.
+**/
+EFI_STATUS
+EFIAPI
+GetTimerValue (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ );
+
+/**
+ Set memory cacheability attributes for given range of memeory
+
+ @param[in] This - Protocol instance structure
+ @param[in] BaseAddress - Specifies the start address of the memory range
+ @param[in] Length - Specifies the length of the memory range
+ @param[in] Attributes - The memory cacheability for the memory range
+
+ @retval EFI_SUCCESS - If the cacheability of that memory range is set successfully
+ @exception EFI_UNSUPPORTED - If the desired operation cannot be done
+ @retval EFI_INVALID_PARAMETER - The input parameter is not correct, such as Length = 0
+**/
+EFI_STATUS
+EFIAPI
+SetMemoryAttributes (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ );
+
+/**
+ Init Global Descriptor table
+**/
+VOID
+InitializeSelectors (
+ VOID
+ );
+
+typedef struct {
+ VOID *Start;
+ UINTN Size;
+ UINTN FixOffset;
+} INTERRUPT_HANDLER_TEMPLATE_MAP;
+
+typedef union {
+ EFI_CPU_DATA_RECORD *DataRecord;
+ UINT8 *Raw;
+} EFI_CPU_DATA_RECORD_BUFFER;
+
+///
+/// This constant defines the maximum length of the CPU brand string. According to the
+/// IA manual, the brand string is in EAX through EDX (thus 16 bytes) after executing
+/// the CPUID instructions with EAX as 80000002, 80000003, 80000004.
+///
+#define MAXIMUM_CPU_BRAND_STRING_LENGTH 48
+
+typedef struct {
+ BOOLEAN StringValid;
+ CHAR16 BrandString[MAXIMUM_CPU_BRAND_STRING_LENGTH + 1];
+ EFI_PROCESSOR_VERSION_DATA StringRef;
+} PROCESSOR_VERSION_INFORMATION;
+
+///
+/// The constant defines how many times the Cpuid instruction should be executed
+/// in order to get all the cache information. For Pentium 4 processor, 1 is enough
+///
+#define CPU_CPUID_EXECTION_COUNT 2
+
+typedef struct {
+ UINT64 IntendCoreFrequency;
+ UINT64 IntendFsbFrequency;
+ PROCESSOR_VERSION_INFORMATION Version;
+ EFI_PROCESSOR_MANUFACTURER_DATA Manufacturer;
+ EFI_PROCESSOR_ID_DATA CpuidData;
+ EFI_PROCESSOR_FAMILY_DATA Family;
+ INT16 Voltage;
+ EFI_PROCESSOR_APIC_BASE_ADDRESS_DATA ApicBase;
+ EFI_PROCESSOR_APIC_ID_DATA ApicID;
+ EFI_PROCESSOR_APIC_VERSION_NUMBER_DATA ApicVersion;
+ UINT32 MicrocodeRevision;
+ EFI_PROCESSOR_STATUS_DATA Status; ///< Need to update this field before report
+ CPU_PHYSICAL_LOCATION Location;
+ EFI_MP_HEALTH_FLAGS Health;
+ EFI_CPUID_REGISTER CacheInformation[CPU_CPUID_EXECTION_COUNT];
+} CPU_DATA_FOR_DATAHUB;
+
+///
+/// Type, FamilyId and Model values for the different processors
+/// [0:7] - Model
+/// [8:23] - FamilyId
+/// [24:31] - Type
+///
+#define RESERVED 0x00
+
+/**
+ This will locate a processor microcode and if it finds a newer revision, it will
+ load it to the processor.
+
+ @param[in] MicrocodePointerBuffer - The Array of pointers which each points to 1 microcode update binary (in memory)
+ @param[in] FailedRevision - The microcode revision that fails to be loaded
+
+ @retval EFI_SUCCESS - A new microcode update is loaded
+ @retval Other - Due to some reason, no new microcode update is loaded
+**/
+EFI_STATUS
+InitializeMicrocode (
+ IN EFI_CPU_MICROCODE_HEADER **MicrocodePointerBuffer,
+ OUT UINT32 *FailedRevision
+ );
+
+/**
+ To indicate the first microcode load is done
+**/
+VOID
+McuFirstLoadDone (
+ VOID
+ );
+
+/**
+ Initializes MP support in the system.
+
+ @retval EFI_SUCCESS - Multiple processors are initialized successfully.
+ @retval EFI_NOT_FOUND - The ACPI variable is not found in S3 boot path.
+ @retval EFI_OUT_OF_RESOURCES - No enough resoruces (such as out of memory).
+**/
+EFI_STATUS
+InitializeMpSupport (
+ VOID
+ );
+
+/**
+ Save the MTRR registers to global variables
+**/
+VOID
+ReadMtrrRegisters (
+ VOID
+ );
+
+/**
+ Synch up the MTRR values for all processors
+**/
+VOID
+EFIAPI
+MpMtrrSynchUp (
+ IN VOID *Buffer
+ );
+
+/**
+ Copy Global MTRR data to S3
+**/
+VOID
+SaveBspMtrrForS3 (
+ VOID
+ );
+
+/**
+ Load all microcode updates to memory. Since in S3 resume boot path, CPUs should be
+ patched again, these microcode updates are copied to OS reserved memory.
+
+ @retval EFI_SUCCESS - All microcode updates are loaded to memory successfully
+ @retval EFI_OUT_OF_RESOURCES - Not enough memory to accomodate all the microcode updates
+**/
+EFI_STATUS
+LoadAllMicrocodeUpdates (
+ VOID
+ );
+
+/**
+ Returns the actual CPU core frequency in MHz.
+
+ @param[in] Metronome - Metronome protocol
+ @param[in] Frequency - Pointer to the CPU core frequency
+
+ @retval EFI_SUCCESS - If the frequency is returned successfully
+ @retval EFI_INVALID_PARAMETER - If the input parameter is wrong
+**/
+EFI_STATUS
+GetActualFrequency (
+ IN EFI_METRONOME_ARCH_PROTOCOL *Metronome,
+ OUT UINT64 *Frequency
+ );
+
+/**
+ Dump RC CPU and PPM platform policies
+**/
+VOID
+CpuDxePolicyDump (
+ VOID
+ );
+
+/**
+ Initialize the global DataHub pointer
+
+ @param[in] DataHub - Pointer to the DataHub protocol as output
+
+ @retval EFI_SUCCESS - If the DataHub pointer is initialized successfully
+**/
+EFI_STATUS
+InitializeDataHubPtr (
+ OUT EFI_DATA_HUB_PROTOCOL **DataHub
+ );
+
+/**
+ Check if loading microcode update fails, if so, report proper status code
+
+ @param[in] CpuNumber - The CPU number
+ @param[in] Status - The return value of InitializeMicrocode()
+ @param[in] FailedRevision - The revision of the microcode update that failed to be loaded
+
+ @retval EFI_SUCCESS - The status is check and proper status code is reported
+**/
+EFI_STATUS
+CheckMicrocodeUpdate (
+ IN UINTN CpuNumber,
+ IN EFI_STATUS Status,
+ IN UINT32 FailedRevision
+ );
+
+/**
+ Enable Cpu Interrupt
+**/
+VOID
+CpuEnableInterrupt (
+ VOID
+ );
+
+/**
+ Disable Cpu Interrupt
+**/
+VOID
+CpuDisableInterrupt (
+ VOID
+ );
+
+/**
+ Get code segment
+
+ @retval Code segmnet value
+**/
+UINT16
+GetCodeSegment (
+ VOID
+ );
+
+/**
+ Initialize Cpu float point unit
+**/
+VOID
+CpuInitFloatPointUnit (
+ VOID
+ );
+
+/**
+ Drop into SMM to register IOTRAP handler for pfat tools interface
+
+ @param[in] Event - A pointer to the Event that triggered the callback.
+ @param[in] Context - A pointer to private data registered with the callback function.
+**/
+VOID
+InitializePfatToolsIntCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ Register callback function for Boot Guard revocation flow.
+
+ @param[in] Event - A pointer to the Event that triggered the callback.
+ @param[in] Context - A pointer to private data registered with the callback function.
+**/
+VOID
+EFIAPI
+BootGuardRevocationCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+#endif
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxeStrings.uni b/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxeStrings.uni
new file mode 100644
index 0000000..9dee7a4
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/CpuInitDxeStrings.uni
Binary files differ
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/Exception.h b/ReferenceCode/Haswell/CpuInit/Dxe/Exception.h
new file mode 100644
index 0000000..b8a1eac
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/Exception.h
@@ -0,0 +1,92 @@
+/** @file
+ IA32 Exception Includes.
+
+@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 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
+**/
+#ifndef _IA32EXCEPTION_H
+#define _IA32EXCEPTION_H
+
+//
+// Driver Consumed Protocol Prototypes
+//
+#include EFI_ARCH_PROTOCOL_DEFINITION (Cpu)
+
+#define INTERRUPT_HANDLER_DIVIDE_ZERO 0x00
+#define INTERRUPT_HANDLER_DEBUG 0x01
+#define INTERRUPT_HANDLER_NMI 0x02
+#define INTERRUPT_HANDLER_BREAKPOINT 0x03
+#define INTERRUPT_HANDLER_OVERFLOW 0x04
+#define INTERRUPT_HANDLER_BOUND 0x05
+#define INTERRUPT_HANDLER_INVALID_OPCODE 0x06
+#define INTERRUPT_HANDLER_DEVICE_NOT_AVAILABLE 0x07
+#define INTERRUPT_HANDLER_DOUBLE_FAULT 0x08
+#define INTERRUPT_HANDLER_COPROCESSOR_OVERRUN 0x09
+#define INTERRUPT_HANDLER_INVALID_TSS 0x0A
+#define INTERRUPT_HANDLER_SEGMENT_NOT_PRESENT 0x0B
+#define INTERRUPT_HANDLER_STACK_SEGMENT_FAULT 0x0C
+#define INTERRUPT_HANDLER_GP_FAULT 0x0D
+#define INTERRUPT_HANDLER_PAGE_FAULT 0x0E
+#define INTERRUPT_HANDLER_RESERVED 0x0F
+#define INTERRUPT_HANDLER_MATH_FAULT 0x10
+#define INTERRUPT_HANDLER_ALIGNMENT_FAULT 0x11
+#define INTERRUPT_HANDLER_MACHINE_CHECK 0x12
+#define INTERRUPT_HANDLER_STREAMING_SIMD 0x13
+
+typedef struct {
+ EFI_STATUS_CODE_DATA Header;
+ union {
+ EFI_SYSTEM_CONTEXT_IA32 SystemContextIa32;
+ EFI_SYSTEM_CONTEXT_X64 SystemContextX64;
+ } SystemContext;
+} CPU_STATUS_CODE_TEMPLATE;
+
+/**
+ Common exception handler
+
+ @param[in] InterruptType - Exception type
+ @param[in] SystemContext - EFI_SYSTEM_CONTEXT
+**/
+VOID
+EFIAPI
+CommonExceptionHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ );
+
+/**
+ Install the IA-32 EM64T Exception Handler.
+ The current operation (which likely will change) will uninstall all the
+ pertinent exception handlers (0-7, 10-14, 16-19) except for Int8 which the timer
+ is currently sitting on (or soon will be).
+
+ It then installs all the appropriate handlers for each exception.
+
+ The handler then calls gRT->ReportStatusCode with a specific progress code. The
+ progress codes for now start at 0x200 for IA-32 processors. See Status Code
+ Specification for details. The Status code Specification uses the enumeration from
+ the EFI 1.1 Debug Support Protocol.
+
+ @param[in] CpuProtocol - Instance of CPU Arch Protocol
+
+ @retval EFI_SUCCESS - This function always return success after registering handlers.
+**/
+EFI_STATUS
+InitializeException (
+ IN EFI_CPU_ARCH_PROTOCOL *CpuProtocol
+ );
+
+#endif
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/Features.c b/ReferenceCode/Haswell/CpuInit/Dxe/Features.c
new file mode 100644
index 0000000..2561850
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/Features.c
@@ -0,0 +1,1093 @@
+/** @file
+ CPU feature control module
+
+@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 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
+
+**/
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "CpuInitDxe.h"
+#include "Features.h"
+#include "MachineCheck.h"
+#include "Mpcommon.h"
+#include "CpuPlatformLib.h"
+#endif
+
+extern DXE_CPU_PLATFORM_POLICY_PROTOCOL *mPlatformCpu;
+
+UINT8 mFeatureLock;
+UINTN mCommonFeatures;
+UINTN mSetupFeatures;
+
+static UINT8 mLock;
+static LEAST_FEATURE_PROC mLeastFeatureProcessor;
+
+/**
+ Write 64bits MSR with script
+
+ @param[in] Index - MSR index that will be written
+ @param[in] Value - value written to MSR
+**/
+VOID
+AsmWriteMsr64WithScript (
+ IN UINT32 Index,
+ IN UINT64 Value
+ )
+{
+ AsmWriteMsr64 (Index, Value);
+ WriteMsr64ToScript (Index, Value);
+}
+
+/**
+ Write 64bits MSR to script
+
+ @param[in] Index - MSR index that will be written
+ @param[in] Value - value written to MSR
+**/
+VOID
+WriteMsr64ToScript (
+ IN UINT32 Index,
+ IN UINT64 Value
+ )
+{
+ UINTN TableIndex;
+
+ ASSERT (mMPSystemData != NULL);
+
+ ///
+ /// Save it into script
+ ///
+ AsmAcquireMPLock (&(mMPSystemData->S3BootScriptLock));
+ TableIndex = mMPSystemData->S3BootScriptCount++;
+ AsmReleaseMPLock (&(mMPSystemData->S3BootScriptLock));
+
+ ASSERT (TableIndex < MAX_CPU_S3_TABLE_SIZE - 1);
+ mMPSystemData->S3BootScriptTable[TableIndex].ApicId = GetApicID (NULL, NULL);
+ mMPSystemData->S3BootScriptTable[TableIndex].MsrIndex = Index;
+ mMPSystemData->S3BootScriptTable[TableIndex].MsrValue = Value;
+}
+
+/**
+ Provide access to the CPU misc enables MSR
+
+ @param[in] Enable - Enable or Disable Misc Features
+ @param[in] BitMask - The register bit offset of MSR MSR_IA32_MISC_ENABLE
+**/
+VOID
+CpuMiscEnable (
+ BOOLEAN Enable,
+ UINT64 BitMask
+ )
+{
+ UINT64 MsrValue;
+
+ MsrValue = AsmReadMsr64 (MSR_IA32_MISC_ENABLE);
+ if (Enable) {
+ MsrValue |= BitMask;
+ } else {
+ MsrValue &= ~BitMask;
+ }
+
+ AsmWriteMsr64 (MSR_IA32_MISC_ENABLE, MsrValue);
+}
+
+/**
+ Calculate how many bits are one from given number
+
+ @param[in] Value - number that will be calculated bits
+
+ @retval Number of bits
+**/
+UINT32
+GetBitsNumberOfOne (
+ UINT32 Value
+ )
+{
+ UINT32 Result;
+
+ Result = 0;
+ while (Value) {
+ if (Value & 1) {
+ Result++;
+ }
+ Value >>= 1;
+ }
+ return Result;
+}
+
+///
+/// DCA contains processor code and chipset code
+/// CPU driver has the following assumption on the initialization flow
+/// 1. Chipset pre-initialization should detect DCA support per chipset capability after CpuPlatformPolicy
+/// 2. If not support, it should update CpuPlatformPolicy DCA to disable state
+/// 3. If support, it should enable the DCA related registers
+/// 4. CPU initialization for DCA (CPU may change CpuPlatformPolicy DCA states per CPU capability)
+/// 5. Normal chipset driver (IOH) should look at CpuPlatformPolicy DCA policy again in PCI enumeratoin
+/// 6. Chipset enable or disable DCA according to CpuPlatformPolicy DCA state
+///
+/**
+ Detect DCA supported or not
+
+ @retval DCA_SUPPORT if supported or 0 if not supported
+**/
+UINTN
+IsDcaSupported (
+ VOID
+ )
+{
+ EFI_CPUID_REGISTER CpuidRegisters;
+ BOOLEAN Support;
+
+ Support = 0;
+ AsmCpuid (
+ CPUID_VERSION_INFO,
+ &CpuidRegisters.RegEax,
+ &CpuidRegisters.RegEbx,
+ &CpuidRegisters.RegEcx,
+ &CpuidRegisters.RegEdx
+ );
+ if ((CpuidRegisters.RegEcx & B_CPUID_VERSION_INFO_ECX_DCA) != 0) {
+ ///
+ /// Execute Disable Bit feature is not supported on this processor.
+ ///
+ Support = DCA_SUPPORT;
+ }
+ return Support;
+}
+
+/**
+ Detect HT supported or not
+
+ @retval HT_SUPPORT if supported or 0 if not supported
+**/
+UINTN
+IsHTSupported (
+ VOID
+ )
+{
+ EFI_CPUID_REGISTER CpuidRegisters;
+ UINTN Support;
+
+ Support = 0;
+
+ AsmCpuidEx (
+ CPUID_CORE_TOPOLOGY,
+ 0,
+ &CpuidRegisters.RegEax,
+ &CpuidRegisters.RegEbx,
+ &CpuidRegisters.RegEcx,
+ &CpuidRegisters.RegEdx
+ );
+ if ((CpuidRegisters.RegEbx & 0x00FF) == 2) {
+ Support = HT_SUPPORT;
+ }
+ return Support;
+
+}
+
+/**
+ Detect if AES supported or not
+
+ @retval AES_SUPPORT if supported or 0 if not supported
+**/
+UINTN
+IsAesSupported (
+ VOID
+ )
+{
+
+ EFI_CPUID_REGISTER CpuidRegisters;
+ UINTN Support;
+
+ Support = 0;
+ EfiCpuid (CPUID_VERSION_INFO, &CpuidRegisters);
+ if ((CpuidRegisters.RegEcx & B_CPUID_VERSION_INFO_ECX_AES) != 0) {
+ Support = AES_SUPPORT;
+ }
+ return Support;
+}
+
+/**
+ Detect if XD supported or not
+
+ @retval XD_SUPPORT if supported or 0 if not supported
+**/
+UINTN
+IsXdSupported (
+ VOID
+ )
+{
+ EFI_CPUID_REGISTER CpuidRegisters;
+ BOOLEAN Support;
+
+ Support = 0;
+ AsmCpuid (
+ CPUID_EXTENDED_FUNCTION,
+ &CpuidRegisters.RegEax,
+ &CpuidRegisters.RegEbx,
+ &CpuidRegisters.RegEcx,
+ &CpuidRegisters.RegEdx
+ );
+ if (CpuidRegisters.RegEax > CPUID_EXTENDED_FUNCTION) {
+ AsmCpuid (
+ CPUID_EXTENDED_CPU_SIG,
+ &CpuidRegisters.RegEax,
+ &CpuidRegisters.RegEbx,
+ &CpuidRegisters.RegEcx,
+ &CpuidRegisters.RegEdx
+ );
+ if ((CpuidRegisters.RegEdx & B_CPUID_VERSION_INFO_EDX_XD) != 0) {
+ ///
+ /// Execute Disable Bit feature is not supported on this processor.
+ ///
+ Support = XD_SUPPORT;
+ }
+ }
+ return Support;
+}
+
+/**
+ Enable XD if supported or disable it if not supported
+
+ @param[in] Support - bitmap that indicate XD supported or not
+**/
+VOID
+EnableDisableXd (
+ IN UINTN Support
+ )
+{
+ BOOLEAN XdSupport;
+
+ if ((mCommonFeatures & XD_SUPPORT) == 0) {
+ return;
+ }
+ XdSupport = (BOOLEAN)((Support & XD_SUPPORT) == XD_SUPPORT);
+ ///
+ /// MSR MISC_ENABLE[34] has negative logic: 0 - XD Enabled, 1 - XD Disabled
+ ///
+ CpuMiscEnable (!XdSupport, B_MSR_IA32_MISC_ENABLE_XD);
+}
+
+/**
+ Check on the processor if VMX/TXT is supported.
+
+ @retval VMX_SUPPORT and TXT_SUPPORT if supported or 0 if not supported
+**/
+UINTN
+IsVmxSupported (
+ VOID
+ )
+{
+ EFI_CPUID_REGISTER CpuIdRegister;
+ UINTN Support;
+
+ Support = 0;
+
+ ///
+ /// Get CPUID to check if the processor supports Vanderpool Technology.
+ ///
+ AsmCpuid (
+ CPUID_VERSION_INFO,
+ &CpuIdRegister.RegEax,
+ &CpuIdRegister.RegEbx,
+ &CpuIdRegister.RegEcx,
+ &CpuIdRegister.RegEdx
+ );
+ if ((CpuIdRegister.RegEcx & B_CPUID_VERSION_INFO_ECX_VME) != 0) {
+ ///
+ /// VT is supported.
+ ///
+ Support |= VMX_SUPPORT;
+ }
+ if ((CpuIdRegister.RegEcx & B_CPUID_VERSION_INFO_ECX_SME) != 0) {
+ ///
+ /// TXT is supported.
+ ///
+ Support |= TXT_SUPPORT;
+ }
+ return Support;
+}
+
+/**
+ Enable VMX/TXT on the processor.
+
+ @param[in] Support - To enable or disable VMX/TXT feature.
+**/
+VOID
+EnableDisableVmx (
+ IN UINTN Support
+ )
+{
+ UINT64 Ia32FeatCtrl;
+ UINT64 NewFeatCtrl;
+
+ Ia32FeatCtrl = AsmReadMsr64 (MSR_IA32_FEATURE_CONTROL);
+ Ia32FeatCtrl &= ~((UINT64) OPTION_FEATURE_RESERVED_MASK);
+
+ NewFeatCtrl = Ia32FeatCtrl;
+
+ ///
+ /// If Vmx is Disabled, Enable it.
+ ///
+ if (mCommonFeatures & VMX_SUPPORT) {
+ if (Support & VMX_SUPPORT) {
+ NewFeatCtrl |= B_MSR_IA32_FEATURE_CONTROL_EVT;
+ } else {
+ NewFeatCtrl &= ~B_MSR_IA32_FEATURE_CONTROL_EVT;
+ }
+ }
+ if (mCommonFeatures & TXT_SUPPORT) {
+ if (Support & TXT_SUPPORT) {
+ ///
+ /// MSR Lock will be done in later.
+ ///
+ NewFeatCtrl |= (B_MSR_IA32_FEATURE_CONTROL_SLFE | B_MSR_IA32_FEATURE_CONTROL_SGE);
+ if (mCommonFeatures & VMX_SUPPORT) {
+ ///
+ /// Bit [1] can only be set if CPU is both VMX and TXT capable
+ ///
+ NewFeatCtrl |= B_MSR_IA32_FEATURE_CONTROL_ELT;
+ }
+ } else {
+ NewFeatCtrl &= ~(B_MSR_IA32_FEATURE_CONTROL_ELT | B_MSR_IA32_FEATURE_CONTROL_SLFE | B_MSR_IA32_FEATURE_CONTROL_SGE);
+ }
+ }
+
+ ///
+ /// Check the Feature Lock Bit.
+ /// If it is already set, which indicates we are executing POST
+ /// due to a warm RESET (i.e., PWRGOOD was not de-asserted).
+ ///
+ if ((Ia32FeatCtrl & B_MSR_IA32_FEATURE_CONTROL_LOCK) == 0) {
+ AsmWriteMsr64WithScript (MSR_IA32_FEATURE_CONTROL, NewFeatCtrl);
+ } else {
+ ///
+ /// if Lock bit is set
+ ///
+ NewFeatCtrl &= ~(B_MSR_IA32_FEATURE_CONTROL_LOCK);
+ WriteMsr64ToScript (MSR_IA32_FEATURE_CONTROL, NewFeatCtrl);
+ }
+}
+
+/**
+ Enable / Disable AES on the processor.
+
+ @param[in] Support - To enable or disable AES feature.
+**/
+VOID
+EnableDisableAes (
+ IN UINTN Support
+ )
+{
+ UINT64 MsrValue;
+
+ if (!(mCommonFeatures & AES_SUPPORT) || (IsSecondaryThread ())) {
+ return;
+ }
+
+ ///
+ /// The processor was manufacted with AES-NI feature
+ ///
+ MsrValue = AsmReadMsr64 (MSR_IA32_FEATURE_CONFIG);
+
+ ///
+ /// Check the Feature Lock Bit.
+ /// If it is already set, which indicates we are executing POST
+ /// due to a warm RESET (i.e., PWRGOOD was not de-asserted).
+ ///
+ if ((MsrValue & B_IA32_FEATURE_CONFIG_LOCK) == 0) {
+ if (Support & AES_SUPPORT) {
+ ///
+ /// Enabled AES, writes of 00b, 01b pr 10b to the MSR will result in AES enable.
+ /// Should lock this MSR always, so write 01b to the MSR.
+ ///
+ MsrValue &= ~B_IA32_FEATURE_CONFIG_AES_DIS;
+ MsrValue |= B_IA32_FEATURE_CONFIG_LOCK;
+ } else {
+ ///
+ /// To disable AES, system BIOS must write 11b to this MSR.
+ ///
+ MsrValue |= (B_IA32_FEATURE_CONFIG_AES_DIS + B_IA32_FEATURE_CONFIG_LOCK);
+ }
+ AsmWriteMsr64WithScript (MSR_IA32_FEATURE_CONFIG, MsrValue);
+ }
+ return;
+}
+
+/**
+ Check on the processor if Debug Interface is supported.
+
+ @retval DEBUG_SUPPORT and DEBUG_LOCK_SUPPORT if supported or 0 if not supported
+**/
+UINTN
+IsDebugInterfaceSupported (
+ VOID
+ )
+{
+ UINTN Support;
+ EFI_CPUID_REGISTER CpuIdRegister;
+
+ Support = 0;
+
+ ///
+ /// Access to MSR_IA32_DEBUG_INTERFACE is supported on:
+ /// HSW B0, HSWULT B0 and CRW B0 Stepping
+ /// HSW stepping >= C0, HSWULT Stepping >= C0 and CRW stepping >= C0 stepping, if CPUID (EAX=1): ECX[11] = 1
+ ///
+ AsmCpuid (
+ CPUID_VERSION_INFO,
+ &CpuIdRegister.RegEax,
+ &CpuIdRegister.RegEbx,
+ &CpuIdRegister.RegEcx,
+ &CpuIdRegister.RegEdx
+ );
+ switch (CpuIdRegister.RegEax) {
+ case (EnumCpuHsw + EnumHswA0):
+ //DEBUG ((EFI_D_INFO,"MSR_IA32_DEBUG_INTERFACE is not supported on Ax CPU stepping\n")); (AMI_CHG+)
+ break;
+ case (EnumCpuHsw + EnumHswB0):
+ case (EnumCpuHswUlt + EnumHswUltB0):
+ case (EnumCpuCrw + EnumCrwB0):
+ Support |= DEBUG_SUPPORT;
+ Support |= DEBUG_LOCK_SUPPORT;
+ break;
+ default:
+ if (CpuIdRegister.RegEcx & BIT11) {
+ Support |= DEBUG_SUPPORT;
+ Support |= DEBUG_LOCK_SUPPORT;
+ }
+ break;
+ }
+ return Support;
+}
+
+/**
+ Enable/Disable Debug Interfaces in the processor.
+
+ @param[in] Support - To enable or disable Debug Interface feature.
+**/
+VOID
+EnableDisableDebugInterface (
+ IN UINTN Support
+ )
+{
+ UINT64 Ia32DebugInterface;
+ BOOLEAN IsBsp;
+
+ ///
+ /// IA32_DEBUG_INTERFACE_MSR scope is "Package", program on BSP only
+ ///
+ IsBsp = (AsmReadMsr64 (MSR_IA32_APIC_BASE) & B_MSR_IA32_APIC_BASE_BSP) ? TRUE : FALSE;
+ if (!(mCommonFeatures & DEBUG_SUPPORT) || (IsBsp == FALSE)) {
+ return;
+ }
+
+ ///
+ /// Check if the processor supports debug interface
+ ///
+ if (IsDebugInterfaceSupported()) {
+ Ia32DebugInterface = AsmReadMsr64 (MSR_IA32_DEBUG_INTERFACE);
+ if (!(Ia32DebugInterface & B_DEBUG_INTERFACE_LOCK)) {
+ if (Support & DEBUG_SUPPORT) {
+ ///
+ /// Enable Debug Interface (MSR 0xC80.Bit0 = 1)
+ ///
+ Ia32DebugInterface |= B_DEBUG_INTERFACE_ENABLE;
+ DEBUG ((EFI_D_ERROR, "Enable MSR_IA32_DEBUG_INTERFACE\n"));
+ } else {
+ ///
+ /// Disable Debug Interface (MSR 0xC80.Bit0 = 0)
+ ///
+ Ia32DebugInterface &= ~B_DEBUG_INTERFACE_ENABLE;
+ DEBUG ((EFI_D_ERROR, "Disable MSR_IA32_DEBUG_INTERFACE\n"));
+ }
+ if (Support & DEBUG_LOCK_SUPPORT) {
+ Ia32DebugInterface &= ~B_DEBUG_INTERFACE_LOCK;
+ }
+ DEBUG ((EFI_D_ERROR, "Set MSR_IA32_DEBUG_INTERFACE to %x\n",Ia32DebugInterface));
+ AsmWriteMsr64WithScript (MSR_IA32_DEBUG_INTERFACE, Ia32DebugInterface);
+ }
+ }
+ return;
+}
+
+/**
+ Lock VMX/TXT feature bits on the processor.
+ Set "CFG Lock" (MSR 0E2h Bit[15]
+
+ @param[in] LockFeatureEnable - TRUE to lock these feature bits and FALSE to not lock
+**/
+VOID
+LockFeatureBit (
+ IN BOOLEAN LockFeatureEnable
+ )
+{
+ UINT64 Ia32FeatCtrl;
+ UINT32 MsrValue;
+
+ if (!LockFeatureEnable) {
+ return;
+ }
+
+ ///
+ /// MSR 3Ah for VMX/TXT Lock
+ ///
+ Ia32FeatCtrl = AsmReadMsr64 (MSR_IA32_FEATURE_CONTROL);
+ Ia32FeatCtrl &= ~((UINT64) OPTION_FEATURE_RESERVED_MASK);
+
+ if ((Ia32FeatCtrl & B_MSR_IA32_FEATURE_CONTROL_LOCK) == 0) {
+ ///
+ /// Set Feature Lock bits.
+ ///
+ Ia32FeatCtrl |= B_MSR_IA32_FEATURE_CONTROL_LOCK;
+ AsmWriteMsr64WithScript (MSR_IA32_FEATURE_CONTROL, Ia32FeatCtrl);
+ } else {
+ WriteMsr64ToScript (MSR_IA32_FEATURE_CONTROL, Ia32FeatCtrl);
+ }
+
+ MsrValue = GetCsrDesiredCores ();
+ if ((MsrValue & BIT16) == 0) {
+ ///
+ /// Set Lock
+ ///
+ SetLockCsrDesiredCores ();
+ }
+ return;
+}
+
+/**
+ Detect if X2APIC supported or not
+
+ @retval XAPIC_SUPPORT if supported or 0 if not supported
+**/
+UINTN
+IsXapicSupported (
+ VOID
+ )
+{
+ EFI_CPUID_REGISTER CpuidRegisters;
+ UINTN Support;
+ UINT64 MsrValue;
+
+ Support = 0;
+
+ MsrValue = AsmReadMsr64 (MSR_IA32_APIC_BASE);
+ AsmCpuid (
+ CPUID_VERSION_INFO,
+ &CpuidRegisters.RegEax,
+ &CpuidRegisters.RegEbx,
+ &CpuidRegisters.RegEcx,
+ &CpuidRegisters.RegEdx
+ );
+ if ((CpuidRegisters.RegEcx & B_CPUID_VERSION_INFO_ECX_XAPIC) != 0) {
+ if (MsrValue & B_MSR_IA32_APIC_BASE_G_XAPIC) {
+ ///
+ /// XAPIC Mode feature is supported on this processor.
+ ///
+ Support = XAPIC_SUPPORT;
+ }
+ }
+ return Support;
+}
+
+/**
+ Enable / Disable X2APIC on the processor.
+
+ @param[in] Support - To enable or disable X2APIC feature.
+**/
+VOID
+EnableDisableXAPIC (
+ IN UINTN Support
+ )
+{
+ UINT64 MsrValue;
+
+ if (!(mCommonFeatures & XAPIC_SUPPORT)) {
+ return;
+ }
+ MsrValue = AsmReadMsr64 (MSR_IA32_APIC_BASE);
+ if (Support & XAPIC_SUPPORT) {
+ MsrValue |= B_MSR_IA32_APIC_BASE_M_XAPIC;
+ } else {
+ MsrValue &= ~B_MSR_IA32_APIC_BASE_G_XAPIC;
+ MsrValue &= ~B_MSR_IA32_APIC_BASE_M_XAPIC;
+ AsmWriteMsr64 (MSR_IA32_APIC_BASE, MsrValue);
+ MsrValue |= B_MSR_IA32_APIC_BASE_G_XAPIC;
+ }
+ AsmWriteMsr64 (MSR_IA32_APIC_BASE, MsrValue);
+}
+
+/**
+ Initialize other processor functions (TPR messaging, floating point)
+**/
+VOID
+InitializeMiscProcessorFunctions (
+ VOID
+ )
+{
+ UINT64 MsrValue;
+
+ ///
+ /// Enable TPR Update messages,if supported (see section 2.5)
+ ///
+ MsrValue = AsmReadMsr64 (PIC_THREAD_CONTROL);
+ MsrValue &= (~B_PIC_THREAD_CONTROL_TPR_DIS);
+ AsmWriteMsr64WithScript (PIC_THREAD_CONTROL, MsrValue);
+
+ ///
+ /// Enable the Save Floating Point feature on every logical processors in the
+ /// platform when available. The BIOS must verify the SMM SAVE CONTROL capability
+ /// bit is set to 1 in PLATFORM_INFO MSR CEh [16] (see Section 2.16) before setting
+ /// the SMM_SAVE_CONTROL MSR 3Eh [0] to 1.
+ ///
+ MsrValue = AsmReadMsr64 (MSR_PLATFORM_INFO);
+ if ((MsrValue & B_PLATFORM_INFO_SMM_SAVE_CONTROL) != 0) {
+ MsrValue = AsmReadMsr64 (MSR_IA32_SMM_SAVE_CONTROL);
+ MsrValue |= B_MSR_IA32_SMM_SAVE_CONTROL_SFPPE;
+ AsmWriteMsr64WithScript (MSR_IA32_SMM_SAVE_CONTROL, MsrValue);
+ }
+
+}
+
+/**
+ Create feature control structure which will be used to program each feature on each core.
+
+ @param[in] MPSystemData - MP_SYSTEM_DATA global variable that contains platform policy protocol settings of each features.
+**/
+VOID
+InitializeFeaturePerSetup (
+ IN MP_SYSTEM_DATA *MPSystemData
+ )
+{
+ mFeatureLock = VacantFlag;
+ mCommonFeatures = (UINTN) -1;
+ mSetupFeatures = (UINTN) -1;
+
+ if (!MPSystemData->VmxEnable) {
+ mSetupFeatures &= ~VMX_SUPPORT;
+ }
+ if (!MPSystemData->TxtEnable) {
+ mSetupFeatures &= ~TXT_SUPPORT;
+ }
+ if (!MPSystemData->ExecuteDisableBit) {
+ mSetupFeatures &= ~XD_SUPPORT;
+ }
+ if (!MPSystemData->XapicEnable) {
+ mSetupFeatures &= ~XAPIC_SUPPORT;
+ }
+ if (!MPSystemData->AesEnable) {
+ mSetupFeatures &= ~AES_SUPPORT;
+ }
+ if (!MPSystemData->DebugInterfaceEnable) {
+ mSetupFeatures &= ~DEBUG_SUPPORT;
+ }
+ if (!MPSystemData->DebugInterfaceLockEnable) {
+ mSetupFeatures &= ~DEBUG_LOCK_SUPPORT;
+ }
+}
+
+/**
+ Detect each processor feature and log all supported features
+
+ @param[in] MpServices - EFI_MP_SERVICES_PROTOCOL
+**/
+VOID
+CollectProcessorFeature (
+ IN EFI_MP_SERVICES_PROTOCOL *MpServices
+ )
+{
+ UINTN Support;
+
+ Support = 0;
+ Support |= IsXdSupported ();
+ Support |= IsVmxSupported ();
+ Support |= IsDcaSupported ();
+ Support |= IsAesSupported ();
+ Support |= IsXapicSupported ();
+ Support |= IsHTSupported ();
+ Support |= IsDebugInterfaceSupported ();
+
+ AsmAcquireMPLock (&mFeatureLock);
+ mCommonFeatures &= Support;
+ AsmReleaseMPLock (&mFeatureLock);
+
+ return;
+}
+
+/**
+ Program all processor features basing on desired settings
+
+ @param[in] MpServices - EFI_MP_SERVICES_PROTOCOL
+**/
+VOID
+ProgramProcessorFeature (
+ IN EFI_MP_SERVICES_PROTOCOL *MpServices
+ )
+{
+ UINTN Supported;
+ BOOLEAN IsBsp;
+
+ Supported = mCommonFeatures & mSetupFeatures;
+
+ ///
+ /// Configure features such as Xd, Vmx, Smx, XAPIC, AES, DebugInterface
+ ///
+ EnableDisableXd (Supported);
+ EnableDisableVmx (Supported);
+ EnableDisableXAPIC (Supported);
+ EnableDisableAes (Supported);
+ EnableDisableDebugInterface (Supported);
+
+ ///
+ /// Lock Proceesor Features
+ /// Make sure all CPU Features configuration are set before lock
+ ///
+ LockFeatureBit (1);
+
+ ///
+ /// Programe XApic register
+ ///
+ IsBsp = (AsmReadMsr64 (MSR_IA32_APIC_BASE) & B_MSR_IA32_APIC_BASE_BSP) ? TRUE : FALSE;
+ ProgramXApic (IsBsp);
+
+ ///
+ /// Initialize MonitorMWait register
+ ///
+ CpuMiscEnable (mMPSystemData->MonitorMwaitEnable, B_MSR_IA32_MISC_ENABLE_MONITOR);
+
+ ///
+ /// Initialize Machine Check registers
+ ///
+ InitializeMachineCheckRegisters (NULL, mMPSystemData->MachineCheckEnable);
+
+ //
+ // Misc functions
+ //
+ InitializeMiscProcessorFunctions();
+
+ return;
+}
+
+/**
+ Program CPUID Limit before booting to OS
+
+ @param[in] MpServices - MP Services Protocol entry
+**/
+VOID
+ProgramCpuidLimit (
+ IN EFI_MP_SERVICES_PROTOCOL *MpServices
+ )
+{
+ UINT64 MsrValue;
+
+ ///
+ /// Move Limit CPUID Maxval configuration here to not impact the BOOT
+ /// After setting this, no code can execute CPUID function > 3.
+ ///
+ CpuMiscEnable (mMPSystemData->LimitCpuidMaximumValue, B_MSR_IA32_MISC_ENABLE_CPUID_MAX);
+
+ ///
+ /// Finally record the MISC MSR into CPU S3 script table
+ /// to avoid access for multiple times
+ ///
+ MsrValue = AsmReadMsr64 (MSR_IA32_MISC_ENABLE);
+ AsmWriteMsr64WithScript (MSR_IA32_MISC_ENABLE, MsrValue);
+
+ return;
+}
+
+/**
+ Initialize prefetcher settings
+
+ @param[in] MlcStreamerprefecterEnabled - Enable/Disable MLC streamer prefetcher
+ @param[in] MlcSpatialPrefetcherEnabled - Enable/Disable MLC spatial prefetcher
+**/
+VOID
+InitializeProcessorsPrefetcher (
+ IN UINTN MlcStreamerprefecterEnabled,
+ IN UINTN MlcSpatialPrefetcherEnabled
+ )
+{
+ UINT64 MsrValue;
+ MsrValue = AsmReadMsr64 (MISC_FEATURE_CONTROL);
+
+ if (MlcStreamerprefecterEnabled == CPU_FEATURE_DISABLE) {
+ MsrValue |= B_MISC_FEATURE_CONTROL_MLC_STRP;
+ }
+
+ if (MlcSpatialPrefetcherEnabled == CPU_FEATURE_DISABLE) {
+ MsrValue |= B_MISC_FEATURE_CONTROL_MLC_SPAP;
+ }
+
+ if ((MsrValue & (B_MISC_FEATURE_CONTROL_MLC_STRP | B_MISC_FEATURE_CONTROL_MLC_SPAP)) != 0) {
+ AsmWriteMsr64 (MISC_FEATURE_CONTROL, MsrValue);
+ }
+
+ return;
+}
+
+/**
+ Get processor feature
+
+ @param[in] Features - pointer to a buffer which stores feature information
+**/
+VOID
+GetProcessorFeatures (
+ IN UINT32 *Features
+ )
+{
+ EFI_CPUID_REGISTER CpuidRegisters;
+
+ AsmCpuid (
+ CPUID_VERSION_INFO,
+ &CpuidRegisters.RegEax,
+ &CpuidRegisters.RegEbx,
+ &CpuidRegisters.RegEcx,
+ &CpuidRegisters.RegEdx
+ );
+ Features[0] = CpuidRegisters.RegEcx;
+ Features[1] = CpuidRegisters.RegEdx;
+ AsmCpuid (
+ CPUID_EXTENDED_CPU_SIG,
+ &CpuidRegisters.RegEax,
+ &CpuidRegisters.RegEbx,
+ &CpuidRegisters.RegEcx,
+ &CpuidRegisters.RegEdx
+ );
+ Features[2] = CpuidRegisters.RegEax;
+ Features[3] = CpuidRegisters.RegEbx;
+ Features[4] = CpuidRegisters.RegEcx;
+ Features[5] = CpuidRegisters.RegEdx;
+
+ return;
+}
+
+/**
+ Update some processor info into LEAST_FEATURE_PROC data structure.
+
+ @param[in] Index - indicate which processor calling this routine
+ @param[in] LeastFeatureProcessor - the data structure that will be updated
+**/
+VOID
+UpdateProcessorInfo (
+ IN UINTN Index,
+ IN LEAST_FEATURE_PROC *LeastFeatureProcessor
+ )
+{
+ UINT16 FamilyId;
+ UINT8 Model;
+ UINT8 SteppingId;
+
+ EfiCpuVersion (&FamilyId, &Model, &SteppingId, NULL);
+ LeastFeatureProcessor->Index = Index;
+ LeastFeatureProcessor->ApicId = GetApicID (NULL, NULL);
+ LeastFeatureProcessor->Version = EfiMakeCpuVersion (FamilyId, Model, SteppingId);
+}
+
+/**
+ Get processor feature delta
+
+ @param[in] FeaturesInput - Supported features for input processor
+ @param[in] CommonFeatures - Supported features for processor (subset of FeaturesInput)
+
+ @retval The least of processor features
+**/
+UINT32
+GetProcessorFeatureDelta (
+ IN UINT32 *FeaturesInput,
+ IN UINT32 *CommonFeatures
+ )
+{
+ UINT32 Delta;
+ UINTN Index;
+
+ ///
+ /// CommonFeatures is the subset of FeaturesInput
+ ///
+ Delta = 0;
+ for (Index = 0; Index < MAX_FEATURE_NUM; Index++) {
+ Delta += GetBitsNumberOfOne (FeaturesInput[Index] - CommonFeatures[Index]);
+ }
+
+ return 0;
+}
+
+/**
+ Find out the common features supported by all core/threads
+
+ @param[in] MpServices - EFI_MP_SERVICES_PROTOCOL
+**/
+VOID
+GetProcessorCommonFeature (
+ IN EFI_MP_SERVICES_PROTOCOL *MpServices
+ )
+{
+ UINTN Index;
+ UINT32 Features[MAX_FEATURE_NUM];
+
+ GetProcessorFeatures (Features);
+
+ AsmAcquireMPLock (&mLock);
+ for (Index = 0; Index < MAX_FEATURE_NUM; Index++) {
+ mLeastFeatureProcessor.Features[Index] &= Features[Index];
+ }
+ AsmReleaseMPLock (&mLock);
+ return;
+}
+
+/**
+ Get the processor data with least features
+
+ @param[in] MpServices - EFI_MP_SERVICES_PROTOCOL
+**/
+VOID
+GetProcessorWithLeastFeature (
+ IN EFI_MP_SERVICES_PROTOCOL *MpServices
+ )
+{
+ EFI_STATUS Status;
+ UINTN CurrentProcessor;
+ LEAST_FEATURE_PROC LeastFeatureProcessor;
+
+ Status = MpServices->WhoAmI (
+ MpServices,
+ &CurrentProcessor
+ );
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ GetProcessorFeatures (LeastFeatureProcessor.Features);
+ LeastFeatureProcessor.FeatureDelta = GetProcessorFeatureDelta (
+ LeastFeatureProcessor.Features,
+ mLeastFeatureProcessor.Features
+ );
+
+ AsmAcquireMPLock (&mLock);
+ if (LeastFeatureProcessor.FeatureDelta < mLeastFeatureProcessor.FeatureDelta) {
+ mLeastFeatureProcessor.FeatureDelta = LeastFeatureProcessor.FeatureDelta;
+ UpdateProcessorInfo (CurrentProcessor, &mLeastFeatureProcessor);
+ } else if (LeastFeatureProcessor.FeatureDelta == mLeastFeatureProcessor.FeatureDelta) {
+ UpdateProcessorInfo (CurrentProcessor, &LeastFeatureProcessor);
+ if (LeastFeatureProcessor.Version < mLeastFeatureProcessor.Version) {
+ UpdateProcessorInfo (CurrentProcessor, &mLeastFeatureProcessor);
+ } else if (LeastFeatureProcessor.Version == mLeastFeatureProcessor.Version) {
+ if (LeastFeatureProcessor.ApicId < mLeastFeatureProcessor.ApicId) {
+ UpdateProcessorInfo (CurrentProcessor, &mLeastFeatureProcessor);
+ }
+ }
+ }
+
+ AsmReleaseMPLock (&mLock);
+
+ return;
+}
+
+/**
+ Switch BSP to the processor which has least features
+
+ @param[in] MpServices - EFI_MP_SERVICES_PROTOCOL
+
+ @retval EFI_STATUS - status code returned from each sub-routines
+**/
+EFI_STATUS
+SwitchToLowestFeatureProcess (
+ IN EFI_MP_SERVICES_PROTOCOL *MpServices
+ )
+{
+ EFI_STATUS Status;
+ UINTN CurrentProcessor;
+ UINTN NewBsp;
+ UINT32 Features[MAX_FEATURE_NUM];
+
+ Status = MpServices->WhoAmI (
+ MpServices,
+ &CurrentProcessor
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ReportStatusCode (
+ EFI_PROGRESS_CODE,
+ EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_PC_BSP_SELECT
+ );
+
+ ///
+ /// Take current BSP as the least feature
+ ///
+ UpdateProcessorInfo (CurrentProcessor, &mLeastFeatureProcessor);
+ GetProcessorFeatures (mLeastFeatureProcessor.Features);
+ CopyMem (Features, mLeastFeatureProcessor.Features, sizeof (Features));
+ Status = MpServices->StartupAllAPs (
+ MpServices,
+ GetProcessorCommonFeature,
+ FALSE,
+ NULL,
+ 100000,
+ (VOID *) MpServices,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ///
+ /// Go through all processors to find the processor with least features
+ ///
+ mLeastFeatureProcessor.FeatureDelta = GetProcessorFeatureDelta (Features, mLeastFeatureProcessor.Features);
+ Status = MpServices->StartupAllAPs (
+ MpServices,
+ GetProcessorWithLeastFeature,
+ FALSE,
+ NULL,
+ 100000,
+ (VOID *) MpServices,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ///
+ /// Switch BSP according
+ ///
+ if (mPlatformCpu->CpuConfig->BspSelection == 16) {
+ ///
+ /// Enable least feature SBSP selection
+ ///
+ NewBsp = mLeastFeatureProcessor.Index;
+ } else {
+ ///
+ /// Do not change the current BSP
+ /// made by SEC
+ ///
+ NewBsp = CurrentProcessor;
+ }
+
+ if (NewBsp != CurrentProcessor) {
+
+ DEBUG ((EFI_D_INFO, "Switch BSP from %d ==> %d\n", CurrentProcessor, NewBsp));
+ Status = MpServices->SwitchBSP (
+ MpServices,
+ NewBsp,
+ TRUE
+ );
+ }
+
+ return Status;
+}
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/Features.h b/ReferenceCode/Haswell/CpuInit/Dxe/Features.h
new file mode 100644
index 0000000..207ddde
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/Features.h
@@ -0,0 +1,145 @@
+/** @file
+ Header file of CPU feature control module
+
+@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 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
+**/
+#ifndef _FEATURES_H_
+#define _FEATURES_H_
+
+#include "CpuInitDxe.h"
+#include "MpService.h"
+
+#define OPTION_FEATURE_RESERVED_MASK 0xFFFF00F8 ///< bits 30:16, 7:3
+#define OPTION_FEATURE_CONFIG_RESERVED_MASK 0xFFFFFFFC ///< bits 2:31
+/**
+ Create feature control structure which will be used to program each feature on each core.
+
+ @param[in] MPSystemData - MP_SYSTEM_DATA global variable that contains platform policy protocol settings of each features.
+**/
+VOID
+InitializeFeaturePerSetup (
+ IN MP_SYSTEM_DATA *MPSystemData
+ );
+
+/**
+ Program all processor features basing on desired settings
+
+ @param[in] MpServices - EFI_MP_SERVICES_PROTOCOL
+**/
+VOID
+ProgramProcessorFeature (
+ IN EFI_MP_SERVICES_PROTOCOL *MpServices
+ );
+
+/**
+ Program CPUID Limit before booting to OS
+
+ @param[in] MpServices - MP Services Protocol entry
+**/
+VOID
+ProgramCpuidLimit (
+ IN EFI_MP_SERVICES_PROTOCOL *MpServices
+ );
+
+/**
+ Initialize prefetcher settings
+
+ @param[in] MlcStreamerprefecterEnabled - Enable/Disable MLC streamer prefetcher
+ @param[in] MlcSpatialPrefetcherEnabled - Enable/Disable MLC spatial prefetcher
+**/
+VOID
+InitializeProcessorsPrefetcher (
+ IN UINTN MlcStreamerprefecterEnabled,
+ IN UINTN MlcSpatialPrefetcherEnabled
+ );
+
+/**
+ Detect each processor feature and log all supported features
+
+ @param[in] MpServices - EFI_MP_SERVICES_PROTOCOL
+**/
+VOID
+CollectProcessorFeature (
+ IN EFI_MP_SERVICES_PROTOCOL *MpServices
+ );
+
+/**
+ Lock VMX/TXT feature bits on the processor.
+ Set "CFG Lock" (MSR 0E2h Bit[15]
+
+ @param[in] LockFeatureEnable - TRUE to lock these feature bits and FALSE to not lock
+**/
+VOID
+LockFeatureBit (
+ IN BOOLEAN LockFeatureEnable
+ );
+
+/**
+ Function to get desired core number by CSR register
+
+ @retval Desired core number
+**/
+UINT32
+GetCsrDesiredCores (
+ VOID
+ );
+
+/**
+ Function to set desired core numbers or SMT lock
+**/
+VOID
+SetLockCsrDesiredCores (
+ VOID
+ );
+
+/**
+ Write 64bits MSR with script
+
+ @param[in] Index - MSR index that will be written
+ @param[in] Value - value written to MSR
+**/
+VOID
+AsmWriteMsr64WithScript (
+ IN UINT32 Index,
+ IN UINT64 Value
+ );
+
+/**
+ Write 64bits MSR to script
+
+ @param[in] Index - MSR index that will be written
+ @param[in] Value - value written to MSR
+**/
+VOID
+WriteMsr64ToScript (
+ IN UINT32 Index,
+ IN UINT64 Value
+ );
+
+/**
+ Provide access to the CPU misc enables MSR
+
+ @param[in] Enable - Enable or Disable Misc Features
+ @param[in] BitMask - The register bit offset of MSR MSR_IA32_MISC_ENABLE
+**/
+VOID
+CpuMiscEnable (
+ BOOLEAN Enable,
+ UINT64 BitMask
+ );
+
+#endif
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/MachineCheck.c b/ReferenceCode/Haswell/CpuInit/Dxe/MachineCheck.c
new file mode 100644
index 0000000..b7485fa
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/MachineCheck.c
@@ -0,0 +1,133 @@
+/** @file
+ Machine check register initialization
+
+@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 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
+**/
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "MachineCheck.h"
+#include "Features.h"
+
+#include EFI_GUID_DEFINITION (PowerOnHob)
+#include EFI_PROTOCOL_DEFINITION (MpService)
+#include EFI_PROTOCOL_DEFINITION (CpuPlatformPolicy)
+#endif
+
+extern DXE_CPU_PLATFORM_POLICY_PROTOCOL *mPlatformCpu;
+
+/**
+ Initialize all the Machine-Check registers.
+
+ @param[in] Buffer - Pointer to private data. Not Used.
+ @param[in] MchkEnable - Enable or disable Mchk.
+**/
+VOID
+InitializeMachineCheckRegisters (
+ IN VOID *Buffer,
+ IN BOOLEAN MchkEnable
+ )
+{
+ EFI_CPUID_REGISTER CpuidRegisters;
+ CPU_FEATURE Feature;
+ CPU_IA32_MCG_CAP_LOW_REGISTER *MCGCap;
+ UINT64 MCGCapValue;
+ UINT8 Count;
+ UINT8 Index;
+ UINT8 StartIndex;
+ UINT64 Value;
+
+ if (!MchkEnable) {
+ ///
+ /// Do not enable MCHK
+ ///
+ return;
+ }
+
+ AsmCpuid (
+ CPUID_VERSION_INFO,
+ &CpuidRegisters.RegEax,
+ &CpuidRegisters.RegEbx,
+ &CpuidRegisters.RegEcx,
+ &CpuidRegisters.RegEdx
+ );
+ *(UINT32 *) (&Feature) = CpuidRegisters.RegEdx;
+
+ if (Feature.MCE && Feature.MCA) {
+
+ MCGCapValue = AsmReadMsr64 (IA32_MCG_CAP);
+ MCGCap = (CPU_IA32_MCG_CAP_LOW_REGISTER *) &MCGCapValue;
+
+ Count = (UINT8) MCGCap->Count;
+
+ StartIndex = 0;
+ for (Index = StartIndex; Index < Count; Index++) {
+ Value = (UINT64) -1;
+ AsmWriteMsr64WithScript (IA32_MC0_CTL + Index * 4, Value);
+ }
+ for (Index = StartIndex; Index < Count; Index++) {
+ if (Index <= 4) {
+ ///
+ /// Clean MC0-MC4 Status when system is cold reset, but no boot script. S3 is treated as warm reset.
+ ///
+ if (mPlatformCpu->CpuConfig->IsColdReset == CPU_FEATURE_ENABLE) {
+ AsmWriteMsr64 (IA32_MC0_STATUS + Index * 4, 0);
+ }
+ continue;
+ }
+ AsmWriteMsr64WithScript (IA32_MC0_STATUS + Index * 4, 0);
+ }
+ EnableMce ();
+ }
+
+ return;
+}
+
+/**
+ Enable MCE feature for current CPU.
+
+ @param[in] MchkEnable - Enable Mchk or not.
+**/
+VOID
+InitializeMce (
+ IN BOOLEAN MchkEnable
+ )
+{
+ EFI_CPUID_REGISTER CpuidRegisters;
+ CPU_FEATURE Feature;
+
+ if (!MchkEnable) {
+ ///
+ /// Do not enable MCHK
+ ///
+ return;
+ }
+
+ AsmCpuid (
+ CPUID_VERSION_INFO,
+ &CpuidRegisters.RegEax,
+ &CpuidRegisters.RegEbx,
+ &CpuidRegisters.RegEcx,
+ &CpuidRegisters.RegEdx
+ );
+ *(UINT32 *) (&Feature) = CpuidRegisters.RegEdx;
+
+ if (Feature.MCE && Feature.MCA) {
+ EnableMce ();
+ }
+
+ return;
+}
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/MachineCheck.h b/ReferenceCode/Haswell/CpuInit/Dxe/MachineCheck.h
new file mode 100644
index 0000000..107c849
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/MachineCheck.h
@@ -0,0 +1,109 @@
+/** @file
+ The header file for Machine check register initialization driver
+
+@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 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
+**/
+#ifndef _MACHINE_CHECK_INIT_H
+#define _MACHINE_CHECK_INIT_H
+
+#include "CpuInitDxe.h"
+#include "MpCommon.h"
+
+#pragma pack(1)
+
+typedef struct {
+ UINT32 FPU : 1;
+ UINT32 VME : 1;
+ UINT32 DE : 1;
+ UINT32 PSE : 1;
+ UINT32 TSC : 1;
+ UINT32 MSR : 1;
+ UINT32 PAE : 1;
+ UINT32 MCE : 1;
+
+ UINT32 CX8 : 1;
+ UINT32 APIC : 1;
+ UINT32 Reserved0 : 1;
+ UINT32 SEP : 1;
+ UINT32 MTRR : 1;
+ UINT32 PGE : 1;
+ UINT32 MCA : 1;
+ UINT32 CMOV : 1;
+
+ UINT32 PAT : 1;
+ UINT32 PSE_36 : 1;
+ UINT32 PSN : 1;
+ UINT32 CLFSH : 1;
+ UINT32 Reserved1 : 1;
+ UINT32 DS : 1;
+ UINT32 ACPI : 1;
+ UINT32 MMX : 1;
+
+ UINT32 FXSR : 1;
+ UINT32 SSE : 1;
+ UINT32 SSE2 : 1;
+ UINT32 SS : 1;
+ UINT32 HTT : 1;
+ UINT32 TM : 1;
+ UINT32 Reserved2 : 1;
+ UINT32 PBE : 1;
+} CPU_FEATURE;
+
+typedef struct {
+ UINT32 Count : 8;
+ UINT32 MCG_CTL_P : 1;
+ UINT32 MCG_EXT_P : 1;
+ UINT32 EXT_CORR_ERR : 1;
+ UINT32 MCG_TES_P : 1;
+ UINT32 Reserved0 : 4;
+ UINT32 MCG_EXT_CNT : 8;
+ UINT32 Reserved1 : 8;
+} CPU_IA32_MCG_CAP_LOW_REGISTER;
+
+#pragma pack()
+
+/**
+ Initialize all the Machine-Check registers.
+
+ @param[in] Buffer - Pointer to private data. Not Used.
+ @param[in] MchkEnable - Enable Mchk or not.
+**/
+VOID
+InitializeMachineCheckRegisters (
+ IN VOID *Buffer,
+ IN BOOLEAN MchkEnable
+ );
+
+/**
+ Enable MCE feature for current CPU.
+
+ @param[in] MchkEnable - Enable Mchk or not.
+**/
+VOID
+InitializeMce (
+ IN BOOLEAN MchkEnable
+ );
+
+/**
+ Enable "Machine Check Enable"
+**/
+VOID
+EnableMce (
+ VOID
+ );
+
+#endif
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/MemoryAttribute.c b/ReferenceCode/Haswell/CpuInit/Dxe/MemoryAttribute.c
new file mode 100644
index 0000000..9132580
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/MemoryAttribute.c
@@ -0,0 +1,895 @@
+/** @file
+ CPU MTRR programming driver
+
+Revision History
+
+@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 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
+
+**/
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "MpService.h"
+#include "MemoryAttribute.h"
+#include "CpuInitDxe.h"
+#endif
+
+FIXED_MTRR mFixedMtrrTable[V_FIXED_MTRR_NUMBER];
+
+FIXED_MTRR mFixedMtrrTable[] = {
+ {
+ IA32_MTRR_FIX64K_00000,
+ 0,
+ 0x10000
+ },
+ {
+ IA32_MTRR_FIX16K_80000,
+ 0x80000,
+ 0x4000
+ },
+ {
+ IA32_MTRR_FIX16K_A0000,
+ 0xA0000,
+ 0x4000
+ },
+ {
+ IA32_MTRR_FIX4K_C0000,
+ 0xC0000,
+ 0x1000
+ },
+ {
+ IA32_MTRR_FIX4K_C8000,
+ 0xC8000,
+ 0x1000
+ },
+ {
+ IA32_MTRR_FIX4K_D0000,
+ 0xD0000,
+ 0x1000
+ },
+ {
+ IA32_MTRR_FIX4K_D8000,
+ 0xD8000,
+ 0x1000
+ },
+ {
+ IA32_MTRR_FIX4K_E0000,
+ 0xE0000,
+ 0x1000
+ },
+ {
+ IA32_MTRR_FIX4K_E8000,
+ 0xE8000,
+ 0x1000
+ },
+ {
+ IA32_MTRR_FIX4K_F0000,
+ 0xF0000,
+ 0x1000
+ },
+ {
+ IA32_MTRR_FIX4K_F8000,
+ 0xF8000,
+ 0x1000
+ },
+};
+
+MTRR_VALUE mFixedMtrrValueTable[] = {
+ {
+ 0,
+ FALSE
+ },
+ {
+ 0,
+ FALSE
+ },
+ {
+ 0,
+ FALSE
+ },
+ {
+ 0,
+ FALSE
+ },
+ {
+ 0,
+ FALSE
+ },
+ {
+ 0,
+ FALSE
+ },
+ {
+ 0,
+ FALSE
+ },
+ {
+ 0,
+ FALSE
+ },
+ {
+ 0,
+ FALSE
+ },
+ {
+ 0,
+ FALSE
+ },
+ {
+ 0,
+ FALSE
+ },
+};
+
+VARIABLE_MTRR mVariableMtrr[V_MAXIMUM_VARIABLE_MTRR_NUMBER];
+UINT32 mUsedMtrr;
+UINT8 mDefaultMemoryType = EFI_MEMORY_UC;
+extern UINT64 mValidMtrrAddressMask;
+extern UINT64 mValidMtrrBitsMask;
+extern BOOLEAN mVariableMtrrChanged;
+extern BOOLEAN mFixedMtrrChanged;
+
+/**
+ Disable Cache MTRR
+**/
+VOID
+PreMtrrChange (
+ VOID
+ )
+{
+ UINT64 TempQword;
+
+ EfiDisableCache ();
+ ///
+ /// Disable Cache MTRR
+ ///
+ TempQword = AsmReadMsr64 (CACHE_IA32_MTRR_DEF_TYPE);
+ TempQword = TempQword &~B_CACHE_MTRR_VALID &~B_CACHE_FIXED_MTRR_VALID;
+ AsmWriteMsr64 (CACHE_IA32_MTRR_DEF_TYPE, TempQword);
+
+ return;
+}
+
+/**
+ Enable Cache MTRR
+**/
+VOID
+PostMtrrChange (
+ VOID
+ )
+{
+ UINT64 TempQword;
+
+ TempQword = 0;
+ ///
+ /// Enable Cache MTRR
+ ///
+ TempQword = AsmReadMsr64 (CACHE_IA32_MTRR_DEF_TYPE);
+ AsmWriteMsr64 (CACHE_IA32_MTRR_DEF_TYPE, TempQword | B_CACHE_MTRR_VALID | B_CACHE_FIXED_MTRR_VALID);
+
+ EfiEnableCache ();
+ return;
+}
+
+/**
+ Calculate fixed MTRR
+
+ @param[in] MemoryCacheType - Cache type for this memory range
+ @param[in] Base - Memory range base address
+ @param[in] Length - Memory range length
+
+ @exception EFI_UNSUPPORTED - Fixed MTRR number not enough or not present
+ @retval EFI_SUCCESS - Fixed MTRR settings calculated successfully
+**/
+EFI_STATUS
+CalculateFixedMtrr (
+ IN UINT64 MemoryCacheType,
+ IN UINT64 *Base,
+ IN UINT64 *Length
+ )
+{
+ UINT32 MsrNum;
+ UINT32 ByteShift;
+ UINT64 TempQword;
+ UINT64 OrMask;
+ UINT64 ClearMask;
+
+ TempQword = 0;
+ OrMask = 0;
+ ClearMask = 0;
+
+ for (MsrNum = 0; MsrNum < V_FIXED_MTRR_NUMBER; MsrNum++) {
+ if ((*Base >= mFixedMtrrTable[MsrNum].BaseAddress) &&
+ (*Base < (mFixedMtrrTable[MsrNum].BaseAddress + 8 * mFixedMtrrTable[MsrNum].Length))
+ ) {
+ break;
+ }
+ }
+
+ if (MsrNum == V_FIXED_MTRR_NUMBER) {
+ return EFI_UNSUPPORTED;
+ }
+ ///
+ /// We found the fixed MTRR to be programmed
+ ///
+ for (ByteShift = 0; ByteShift < 8; ByteShift++) {
+ if (*Base == (mFixedMtrrTable[MsrNum].BaseAddress + ByteShift * mFixedMtrrTable[MsrNum].Length)) {
+ break;
+ }
+ }
+
+ if (ByteShift == 8) {
+ return EFI_UNSUPPORTED;
+ }
+
+ for (; ((ByteShift < 8) && (*Length >= mFixedMtrrTable[MsrNum].Length)); ByteShift++) {
+ OrMask |= LShiftU64 ((UINT64) MemoryCacheType, (UINT32) (ByteShift * 8));
+ ClearMask |= LShiftU64 ((UINT64) 0xFF, (UINT32) (ByteShift * 8));
+ *Length -= mFixedMtrrTable[MsrNum].Length;
+ *Base += mFixedMtrrTable[MsrNum].Length;
+ mFixedMtrrChanged = TRUE;
+ }
+
+ if (ByteShift < 8 && (*Length != 0)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ TempQword = AsmReadMsr64 (mFixedMtrrTable[MsrNum].Msr) &~ClearMask | OrMask;
+ mFixedMtrrValueTable[MsrNum].MsrValue = TempQword;
+ mFixedMtrrValueTable[MsrNum].Changed = TRUE;
+ return EFI_SUCCESS;
+}
+
+/**
+ Program fixed MTRR
+**/
+VOID
+ProgramFixedMtrr (
+ VOID
+ )
+{
+ UINT32 MsrNum;
+ PreMtrrChange ();
+ for (MsrNum = 0; MsrNum < V_FIXED_MTRR_NUMBER; MsrNum++) {
+ if (mFixedMtrrValueTable[MsrNum].Changed) {
+ AsmWriteMsr64 (mFixedMtrrTable[MsrNum].Msr, mFixedMtrrValueTable[MsrNum].MsrValue);
+ mFixedMtrrValueTable[MsrNum].Changed = FALSE;
+ }
+ }
+
+ PostMtrrChange ();
+}
+
+/**
+ Get all information about memory cache registers
+
+ @retval EFI_SUCCESS - always success
+**/
+EFI_STATUS
+GetMemoryAttribute (
+ VOID
+ )
+{
+ UINTN Index;
+ UINT32 MsrNum;
+ UINT64 MsrValue;
+ UINT32 VariableMtrrLimit;
+
+ VariableMtrrLimit = (UINT32) (AsmReadMsr64 (IA32_MTRR_CAP) & B_IA32_MTRR_VARIABLE_SUPPORT);
+
+ ///
+ /// Get Default Mtrr Type
+ ///
+ MsrValue = AsmReadMsr64 (CACHE_IA32_MTRR_DEF_TYPE);
+ mDefaultMemoryType = (UINT8) MsrValue;
+
+ ///
+ /// Get Variable Mtrr
+ ///
+ ZeroMem (mVariableMtrr, sizeof (VARIABLE_MTRR) * V_MAXIMUM_VARIABLE_MTRR_NUMBER);
+ mUsedMtrr = 0;
+
+ for (MsrNum = CACHE_VARIABLE_MTRR_BASE, Index = 0;
+ ((MsrNum < (CACHE_VARIABLE_MTRR_BASE + VariableMtrrLimit * 2 - 1)) && (Index < V_MAXIMUM_VARIABLE_MTRR_NUMBER));
+ MsrNum += 2
+ ) {
+ if ((AsmReadMsr64 (MsrNum + 1) & B_CACHE_MTRR_VALID) != 0) {
+ mVariableMtrr[Index].Msr = MsrNum;
+ mVariableMtrr[Index].BaseAddress = (AsmReadMsr64 (MsrNum) & mValidMtrrAddressMask);
+ mVariableMtrr[Index].Length = ((~((AsmReadMsr64 (MsrNum + 1) & mValidMtrrAddressMask))) & mValidMtrrBitsMask) + 1;
+ mVariableMtrr[Index].Type = (AsmReadMsr64 (MsrNum) & 0x0ff);
+ mVariableMtrr[Index].Valid = TRUE;
+ mUsedMtrr++;
+ Index++;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Check if different memory attribute range overlapping with each other
+
+ @param[in] Start - start of memory range that will be checking
+ @param[in] End - end of memory range address that will be checking
+
+ @retval TRUE if overlapping found
+ @retval FALSE if not found
+**/
+BOOLEAN
+CheckMemoryAttributeOverlap (
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN EFI_PHYSICAL_ADDRESS End
+ )
+{
+ UINT32 Index;
+
+ for (Index = 0; Index < V_MAXIMUM_VARIABLE_MTRR_NUMBER; Index++) {
+ if (mVariableMtrr[Index].Valid &&
+ !(
+ Start > (mVariableMtrr[Index].BaseAddress + mVariableMtrr[Index].Length - 1) ||
+ (End < mVariableMtrr[Index].BaseAddress)
+ )
+ ) {
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ Combine current memory attribute range to existing memory attribute range
+
+ @param[in] Attributes - Cache type
+ @param[in] Base - Base address of memory range that will be combined into existing one.
+ @param[in] Length - Length of the memory range that will be combined into existing one.
+
+ @retval EFI_SUCCESS - Memory combined successfully
+ @retval EFI_ACCESS_DENIED - memory type that is not allowed to overlap
+**/
+EFI_STATUS
+CombineMemoryAttribute (
+ IN UINT64 Attributes,
+ IN UINT64 *Base,
+ IN UINT64 *Length
+ )
+{
+ UINT32 Index;
+ UINT64 CombineStart;
+ UINT64 CombineEnd;
+ UINT64 MtrrEnd;
+ UINT64 EndAddress;
+ BOOLEAN InvalidMTRRs[V_MAXIMUM_VARIABLE_MTRR_NUMBER];
+
+ EndAddress = *Base +*Length - 1;
+
+ for (Index = 0; Index < V_MAXIMUM_VARIABLE_MTRR_NUMBER; Index++) {
+ InvalidMTRRs[Index] = FALSE;
+ }
+
+ Index = 0;
+ while (Index < V_MAXIMUM_VARIABLE_MTRR_NUMBER) {
+ MtrrEnd = mVariableMtrr[Index].BaseAddress + mVariableMtrr[Index].Length - 1;
+
+ ///
+ /// The MTRR is marked invalid or the ranges are not intersected.
+ ///
+ if (InvalidMTRRs[Index] ||
+ !mVariableMtrr[Index].Valid ||
+ (*Base > (MtrrEnd) || (EndAddress < mVariableMtrr[Index].BaseAddress))
+ ) {
+ Index++;
+ continue;
+ }
+ ///
+ /// if the requested range contains MTRR range, invalidate this MTRR
+ ///
+ if (mVariableMtrr[Index].BaseAddress >= *Base && MtrrEnd <= EndAddress) {
+ InvalidMTRRs[Index] = TRUE;
+ Index++;
+ continue;
+ }
+
+ if (Attributes == mVariableMtrr[Index].Type) {
+ ///
+ /// if the Mtrr range contain the request range, return EFI_SUCCESS
+ ///
+ if (mVariableMtrr[Index].BaseAddress <= *Base && MtrrEnd >= EndAddress) {
+ *Length = 0;
+ return EFI_SUCCESS;
+ }
+ ///
+ /// invalid this MTRR, and program the combine range
+ ///
+ CombineStart = (*Base) < mVariableMtrr[Index].BaseAddress ? (*Base) : mVariableMtrr[Index].BaseAddress;
+ CombineEnd = EndAddress > MtrrEnd ? EndAddress : MtrrEnd;
+
+ ///
+ /// Record this MTRR as invalid
+ ///
+ InvalidMTRRs[Index] = TRUE;
+
+ ///
+ /// The range is modified, retry from the first MTRR
+ ///
+ if (*Base != CombineStart || *Length != CombineEnd - CombineStart + 1) {
+ Index = 0;
+ } else {
+ Index++;
+ }
+
+ *Base = CombineStart;
+ *Length = CombineEnd - CombineStart + 1;
+ EndAddress = CombineEnd;
+ continue;
+ }
+
+ if ((Attributes == CACHE_UNCACHEABLE) ||
+ (Attributes == CACHE_WRITETHROUGH && mVariableMtrr[Index].Type == CACHE_WRITEBACK) ||
+ (Attributes == CACHE_WRITEBACK && mVariableMtrr[Index].Type == CACHE_WRITETHROUGH) ||
+ (Attributes == CACHE_WRITETHROUGH && mVariableMtrr[Index].Type == CACHE_UNCACHEABLE) ||
+ (Attributes == CACHE_WRITEBACK && mVariableMtrr[Index].Type == CACHE_UNCACHEABLE)
+ ) {
+ Index++;
+ continue;
+ }
+ ///
+ /// Other type memory overlap is invalid
+ ///
+ return EFI_ACCESS_DENIED;
+ }
+ ///
+ /// Finally invalidate recorded MTRRs
+ ///
+ for (Index = 0; Index < V_MAXIMUM_VARIABLE_MTRR_NUMBER; Index++) {
+ if (InvalidMTRRs[Index]) {
+ InvariableMtrr (mVariableMtrr[Index].Msr, Index);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Given the input, check if the number of MTRR is lesser
+ if positive or subtractive
+
+ @param[in] Input - Length of Memory to program MTRR
+ @param[in] MtrrNumber - return needed Mtrr number
+ @param[in] Direction - TRUE: do positive
+ FALSE: do subtractive
+
+ @retval EFI_SUCCESS - always return success
+**/
+EFI_STATUS
+GetDirection (
+ IN UINT64 Input,
+ IN UINTN *MtrrNumber,
+ IN BOOLEAN *Direction
+ )
+{
+ UINT64 TempQword;
+ UINT32 Positive;
+ UINT32 Subtractive;
+
+ TempQword = Input;
+ Positive = 0;
+ Subtractive = 0;
+
+ do {
+ TempQword -= Power2MaxMemory (TempQword);
+ Positive++;
+
+ } while (TempQword != 0);
+
+ TempQword = Power2MaxMemory (LShiftU64 (Input, 1)) - Input;
+ Subtractive++;
+ do {
+ TempQword -= Power2MaxMemory (TempQword);
+ Subtractive++;
+
+ } while (TempQword != 0);
+
+ if (Positive <= Subtractive) {
+ *Direction = TRUE;
+ *MtrrNumber = Positive;
+ } else {
+ *Direction = FALSE;
+ *MtrrNumber = Subtractive;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Calculate max memory of power 2
+
+ @param[in] MemoryLength - Memory length that will be calculated
+
+ @retval Max memory
+**/
+UINT64
+Power2MaxMemory (
+ IN UINT64 MemoryLength
+ )
+{
+ UINT64 Result;
+ UINT32 *ResultPointer;
+ UINT32 *MemoryLengthPointer;
+ MemoryLengthPointer = (UINT32 *) &MemoryLength;
+ ResultPointer = (UINT32 *) &Result;
+ Result = 0;
+ if (MemoryLengthPointer[1] != 0) {
+ ResultPointer[1] = GetPowerOfTwo32 (MemoryLengthPointer[1]);
+ } else {
+ ResultPointer[0] = GetPowerOfTwo32 (MemoryLengthPointer[0]);
+ }
+
+ return Result;
+}
+
+/**
+ Clear MTRR
+
+ @param[in] MtrrNumber - MTRR register that will be cleared
+ @param[in] Index - index of MTRR register
+
+ @retval EFI_SUCCESS - always return success
+**/
+EFI_STATUS
+InvariableMtrr (
+ IN UINTN MtrrNumber,
+ IN UINTN Index
+ )
+{
+ PreMtrrChange ();
+ mVariableMtrr[Index].Valid = FALSE;
+ AsmWriteMsr64 ((UINT32) MtrrNumber, 0);
+ AsmWriteMsr64 ((UINT32) (MtrrNumber + 1), 0);
+ mUsedMtrr--;
+ PostMtrrChange ();
+ return EFI_SUCCESS;
+}
+
+/**
+ Programm VARIABLE MTRR
+
+ @param[in] MtrrNumber - Variable MTRR register
+ @param[in] BaseAddress - Memory base address
+ @param[in] Length - Memory length
+ @param[in] MemoryCacheType - Cache type
+
+ @retval EFI_SUCCESS - always return success
+**/
+EFI_STATUS
+ProgramVariableMtrr (
+ IN UINTN MtrrNumber,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 MemoryCacheType
+ )
+{
+ UINT64 TempQword;
+
+ PreMtrrChange ();
+
+ ///
+ /// MTRR Physical Base
+ ///
+ TempQword = (BaseAddress & mValidMtrrAddressMask) | MemoryCacheType;
+ AsmWriteMsr64 ((UINT32) MtrrNumber, TempQword);
+
+ ///
+ /// MTRR Physical Mask
+ ///
+ TempQword = ~(Length - 1);
+ AsmWriteMsr64 ((UINT32) (MtrrNumber + 1), (TempQword & mValidMtrrAddressMask) | B_CACHE_MTRR_VALID);
+
+ ///
+ /// Variable MTRR is updated
+ ///
+ mVariableMtrrChanged = TRUE;
+
+ PostMtrrChange ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get GCD Mem Space type from Mtrr Type
+
+ @param[in] MtrrAttributes - Mtrr type
+
+ @retval GCD Mem Space typed (64-bit)
+ @retval EFI_MEMORY_UC - input MTRR type is Uncacheable
+ @retval EFI_MEMORY_WC - input MTRR type is Write Combining
+ @retval EFI_MEMORY_WT - input MTRR type is Write-through
+ @retval EFI_MEMORY_WP - input MTRR type is Write-protected
+ @retval EFI_MEMORY_WB - input MTRR type is Write Back
+**/
+UINT64
+GetMemorySpaceAttributeFromMtrrType (
+ IN UINT8 MtrrAttributes
+ )
+{
+ switch (MtrrAttributes) {
+ case CACHE_UNCACHEABLE:
+ return EFI_MEMORY_UC;
+
+ case CACHE_WRITECOMBINING:
+ return EFI_MEMORY_WC;
+
+ case CACHE_WRITETHROUGH:
+ return EFI_MEMORY_WT;
+
+ case CACHE_WRITEPROTECTED:
+ return EFI_MEMORY_WP;
+
+ case CACHE_WRITEBACK:
+ return EFI_MEMORY_WB;
+
+ default:
+ return 0;
+ }
+}
+
+/**
+ Refresh the GCD Memory Space Attributes according to MTRRs
+
+ @retval EFI_STATUS - status returned from each sub-routine
+**/
+EFI_STATUS
+RefreshGcdMemoryAttributes (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN SubIndex;
+ UINT64 RegValue;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT64 Length;
+ UINT64 Attributes;
+ UINT64 CurrentAttributes;
+ UINT8 MtrrType;
+ UINTN NumberOfDescriptors;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;
+ UINT64 DefaultAttributes;
+
+ MemorySpaceMap = NULL;
+
+ Status = GetMemoryAttribute ();
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = gDS->GetMemorySpaceMap (
+ &NumberOfDescriptors,
+ &MemorySpaceMap
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ DefaultAttributes = GetMemorySpaceAttributeFromMtrrType (mDefaultMemoryType);
+
+ ///
+ /// Set default attributes to all spaces.
+ ///
+ for (Index = 0; Index < NumberOfDescriptors; Index++) {
+ if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
+ continue;
+ }
+
+ gDS->SetMemorySpaceAttributes (
+ MemorySpaceMap[Index].BaseAddress,
+ MemorySpaceMap[Index].Length,
+ (MemorySpaceMap[Index].Attributes &~EFI_MEMORY_CACHETYPE_MASK) |
+ (MemorySpaceMap[Index].Capabilities & DefaultAttributes)
+ );
+ }
+ ///
+ /// Go for variable MTRRs, WB first, Other types second
+ ///
+ for (Index = 0; Index < 6; Index++) {
+ if (mVariableMtrr[Index].Valid && mVariableMtrr[Index].Type == CACHE_WRITEBACK) {
+ SetGcdMemorySpaceAttributes (
+ MemorySpaceMap,
+ NumberOfDescriptors,
+ mVariableMtrr[Index].BaseAddress,
+ mVariableMtrr[Index].Length,
+ EFI_MEMORY_WB
+ );
+ }
+ }
+
+ for (Index = 0; Index < 6; Index++) {
+ if (mVariableMtrr[Index].Valid && mVariableMtrr[Index].Type != CACHE_WRITEBACK) {
+ Attributes = GetMemorySpaceAttributeFromMtrrType ((UINT8) mVariableMtrr[Index].Type);
+ SetGcdMemorySpaceAttributes (
+ MemorySpaceMap,
+ NumberOfDescriptors,
+ mVariableMtrr[Index].BaseAddress,
+ mVariableMtrr[Index].Length,
+ Attributes
+ );
+ }
+ }
+ ///
+ /// Go for fixed MTRRs
+ ///
+ Attributes = 0;
+ BaseAddress = 0;
+ Length = 0;
+ for (Index = 0; Index < V_FIXED_MTRR_NUMBER; Index++) {
+ RegValue = AsmReadMsr64 (mFixedMtrrTable[Index].Msr);
+ for (SubIndex = 0; SubIndex < 8; SubIndex++) {
+ MtrrType = (UINT8) RShiftU64 (RegValue, SubIndex * 8);
+ CurrentAttributes = GetMemorySpaceAttributeFromMtrrType (MtrrType);
+ if (Length == 0) {
+ Attributes = CurrentAttributes;
+ } else {
+ if (CurrentAttributes != Attributes) {
+ SetGcdMemorySpaceAttributes (
+ MemorySpaceMap,
+ NumberOfDescriptors,
+ BaseAddress,
+ Length,
+ Attributes
+ );
+ BaseAddress = mFixedMtrrTable[Index].BaseAddress + mFixedMtrrTable[Index].Length * SubIndex;
+ Length = 0;
+ Attributes = CurrentAttributes;
+ }
+ }
+
+ Length += mFixedMtrrTable[Index].Length;
+ }
+ }
+ ///
+ /// handle the last region
+ ///
+ SetGcdMemorySpaceAttributes (
+ MemorySpaceMap,
+ NumberOfDescriptors,
+ BaseAddress,
+ Length,
+ Attributes
+ );
+
+Done:
+ if (MemorySpaceMap != NULL) {
+ FreePool (MemorySpaceMap);
+ }
+
+ return Status;
+}
+
+/**
+ Search into the Gcd Memory Space for descriptors (from StartIndex
+ to EndIndex) that contains the memory range specified by BaseAddress
+ and Length.
+
+ @param[in] MemorySpaceMap - Gcd Memory Space Map as array
+ @param[in] NumberOfDescriptors - Number of descriptors in map
+ @param[in] BaseAddress - BaseAddress for the requested range
+ @param[in] Length - Length for the requested range
+ @param[in] StartIndex - Start index into the Gcd Memory Space Map
+ @param[in] EndIndex - End index into the Gcd Memory Space Map
+
+ @retval EFI_SUCCESS - Search successfully
+ @retval EFI_NOT_FOUND - The requested descriptors not exist
+**/
+EFI_STATUS
+SearchGcdMemorySpaces (
+ IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,
+ IN UINTN NumberOfDescriptors,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ OUT UINTN *StartIndex,
+ OUT UINTN *EndIndex
+ )
+{
+ UINTN Index;
+
+ *StartIndex = 0;
+ *EndIndex = 0;
+ for (Index = 0; Index < NumberOfDescriptors; Index++) {
+ if (BaseAddress >= MemorySpaceMap[Index].BaseAddress &&
+ BaseAddress < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length
+ ) {
+ *StartIndex = Index;
+ }
+
+ if (BaseAddress + Length - 1 >= MemorySpaceMap[Index].BaseAddress &&
+ BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length
+ ) {
+ *EndIndex = Index;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Set the attributes for a specified range in Gcd Memory Space Map.
+
+ @param[in] MemorySpaceMap - Gcd Memory Space Map as array
+ @param[in] NumberOfDescriptors - Number of descriptors in map
+ @param[in] BaseAddress - BaseAddress for the range
+ @param[in] Length - Length for the range
+ @param[in] Attributes - Attributes to set
+
+ @retval EFI_SUCCESS - Set successfully
+ @retval EFI_NOT_FOUND - The specified range does not exist in Gcd Memory Space
+**/
+EFI_STATUS
+SetGcdMemorySpaceAttributes (
+ IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,
+ IN UINTN NumberOfDescriptors,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN StartIndex;
+ UINTN EndIndex;
+ EFI_PHYSICAL_ADDRESS RegionStart;
+ UINT64 RegionLength;
+
+ Status = SearchGcdMemorySpaces (
+ MemorySpaceMap,
+ NumberOfDescriptors,
+ BaseAddress,
+ Length,
+ &StartIndex,
+ &EndIndex
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ for (Index = StartIndex; Index <= EndIndex; Index++) {
+ if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
+ continue;
+ }
+
+ if (BaseAddress >= MemorySpaceMap[Index].BaseAddress) {
+ RegionStart = BaseAddress;
+ } else {
+ RegionStart = MemorySpaceMap[Index].BaseAddress;
+ }
+
+ if (BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {
+ RegionLength = BaseAddress + Length - RegionStart;
+ } else {
+ RegionLength = MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - RegionStart;
+ }
+
+ gDS->SetMemorySpaceAttributes (
+ RegionStart,
+ RegionLength,
+ (MemorySpaceMap[Index].Attributes &~EFI_MEMORY_CACHETYPE_MASK) | (MemorySpaceMap[Index].Capabilities & Attributes)
+ );
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/MemoryAttribute.h b/ReferenceCode/Haswell/CpuInit/Dxe/MemoryAttribute.h
new file mode 100644
index 0000000..8ce2a74
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/MemoryAttribute.h
@@ -0,0 +1,259 @@
+/** @file
+ Header file for CPU MTRR programming driver
+
+Revision History:
+
+@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 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
+**/
+#ifndef _EFI_MEMORY_ATTRIB_H
+#define _EFI_MEMORY_ATTRIB_H
+
+extern UINT32 mUsedMtrr;
+
+typedef struct {
+ UINT32 Msr;
+ UINT32 BaseAddress;
+ UINT32 Length;
+} FIXED_MTRR;
+
+typedef struct {
+ UINT64 MsrValue;
+ BOOLEAN Changed;
+} MTRR_VALUE;
+
+typedef struct {
+ UINT64 BaseAddress;
+ UINT64 Length;
+ UINT64 Type;
+ UINT32 Msr;
+ BOOLEAN Valid;
+} VARIABLE_MTRR;
+
+#define EFI_MEMORY_CACHETYPE_MASK (EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT | EFI_MEMORY_WB | EFI_MEMORY_UCE)
+
+/**
+ Calculate fixed MTRR
+
+ @param[in] MemoryCacheType - Cache type for this memory range
+ @param[in] Base - Memory range base address
+ @param[in] Length - Memory range length
+
+ @exception EFI_UNSUPPORTED - Fixed MTRR number not enough or not present
+ @retval EFI_SUCCESS - Fixed MTRR settings calculated successfully
+**/
+EFI_STATUS
+CalculateFixedMtrr (
+ IN UINT64 MemoryCacheType,
+ IN UINT64 *Base,
+ IN UINT64 *Length
+ );
+
+/**
+ Disable Cache MTRR
+**/
+VOID
+PreMtrrChange (
+ VOID
+ );
+/**
+ Enable Cache MTRR
+**/
+VOID
+PostMtrrChange (
+ VOID
+ );
+
+/**
+ Program fixed MTRR
+**/
+VOID
+ProgramFixedMtrr (
+ VOID
+ );
+
+/**
+ Get all information about memory cache registers
+
+ @retval EFI_SUCCESS - always success
+**/
+EFI_STATUS
+GetMemoryAttribute (
+ VOID
+ );
+
+/**
+ Check if different memory attribute range overlapping with each other
+
+ @param[in] Start - start of memory range that will be checking
+ @param[in] End - end of memory range address that will be checking
+
+ @retval TRUE if overlapping found
+ @retval FALSE if not found
+**/
+BOOLEAN
+CheckMemoryAttributeOverlap (
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN EFI_PHYSICAL_ADDRESS End
+ );
+
+/**
+ Combine current memory attribute range to existing memory attribute range
+
+ @param[in] Attribute - Cache type
+ @param[in] Base - Base address of memory range that will be combined into existing one.
+ @param[in] Length - Length of the memory range that will be combined into existing one.
+
+ @retval EFI_SUCCESS - Memory combined successfully
+ @retval EFI_ACCESS_DENIED - memory type that is not allowed to overlap
+**/
+EFI_STATUS
+CombineMemoryAttribute (
+ IN UINT64 Attribute,
+ IN UINT64 *Base,
+ IN UINT64 *Length
+ );
+
+/**
+ Given the input, check if the number of MTRR is lesser
+ if positive or subtractive
+
+ @param[in] Input - Length of Memory to program MTRR
+ @param[in] MtrrNumber - return needed Mtrr number
+ @param[in] Direction - TRUE: do positive
+ FALSE: do subtractive
+
+ @retval EFI_SUCCESS - always return success
+**/
+EFI_STATUS
+GetDirection (
+ IN UINT64 Input,
+ IN UINTN *MtrrNumber,
+ IN BOOLEAN *Direction
+ );
+
+/**
+ Calculate max memory of power 2
+
+ @param[in] MemoryLength - Memory length that will be calculated
+
+ @retval Max memory
+**/
+UINT64
+Power2MaxMemory (
+ IN UINT64 MemoryLength
+ );
+
+/**
+ Clear MTRR
+
+ @param[in] MtrrNumber - MTRR register that will be cleared
+ @param[in] Index - index of MTRR register
+
+ @retval EFI_SUCCESS - always return success
+**/
+EFI_STATUS
+InvariableMtrr (
+ IN UINTN MtrrNumber,
+ IN UINTN Index
+ );
+
+/**
+ Programm VARIABLE MTRR
+
+ @param[in] MtrrNumber - Variable MTRR register
+ @param[in] BaseAddress - Memory base address
+ @param[in] Length - Memory length
+ @param[in] MemoryCacheType - Cache type
+
+ @retval EFI_SUCCESS - always return success
+**/
+EFI_STATUS
+ProgramVariableMtrr (
+ IN UINTN MtrrNumber,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 MemoryCacheType
+ );
+
+/**
+ Get GCD Mem Space type from Mtrr Type
+
+ @param[in] MtrrAttribute - Mtrr type
+
+ @retval GCD Mem Space typed (64-bit)
+**/
+UINT64
+GetMemorySpaceAttributeFromMtrrType (
+ IN UINT8 MtrrAttribute
+ );
+
+/**
+ Refresh the GCD Memory Space Attributes according to MTRRs
+
+ @retval EFI_STATUS - status returned from each sub-routine
+**/
+EFI_STATUS
+RefreshGcdMemoryAttributes (
+ VOID
+ );
+
+/**
+ Search into the Gcd Memory Space for descriptors (from StartIndex
+ to EndIndex) that contains the memory range specified by BaseAddress
+ and Length.
+
+ @param[in] MemorySpaceMap - Gcd Memory Space Map as array
+ @param[in] NumberOfDescriptors - Number of descriptors in map
+ @param[in] BaseAddress - BaseAddress for the requested range
+ @param[in] Length - Length for the requested range
+ @param[in] StartIndex - Start index into the Gcd Memory Space Map
+ @param[in] EndIndex - End index into the Gcd Memory Space Map
+
+ @retval EFI_SUCCESS - Search successfully
+ @retval EFI_NOT_FOUND - The requested descriptors not exist
+**/
+EFI_STATUS
+SearchGcdMemorySpaces (
+ IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,
+ IN UINTN NumberOfDescriptors,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ OUT UINTN *StartIndex,
+ OUT UINTN *EndIndex
+ );
+
+/**
+ Set the attributes for a specified range in Gcd Memory Space Map.
+
+ @param[in] MemorySpaceMap - Gcd Memory Space Map as array
+ @param[in] NumberOfDescriptors - Number of descriptors in map
+ @param[in] BaseAddress - BaseAddress for the range
+ @param[in] Length - Length for the range
+ @param[in] Attributes - Attributes to set
+
+ @retval EFI_SUCCESS - Set successfully
+ @retval EFI_NOT_FOUND - The specified range does not exist in Gcd Memory Space
+**/
+EFI_STATUS
+SetGcdMemorySpaceAttributes (
+ IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,
+ IN UINTN NumberOfDescriptors,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ );
+#endif
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/Microcode.c b/ReferenceCode/Haswell/CpuInit/Dxe/Microcode.c
new file mode 100644
index 0000000..3f54a7d
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/Microcode.c
@@ -0,0 +1,547 @@
+/** @file
+ CPU Microcode update driver
+
+@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 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
+
+**/
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "CpuInitDxe.h"
+#include "ProcessorData.h"
+#include "MpCommon.h"
+#include "MpService.h"
+#endif
+
+extern DXE_CPU_PLATFORM_POLICY_PROTOCOL *mPlatformCpu;
+
+///
+/// static type so this variable only can be accessed in this file
+///
+static UINT32 mMcuFirstLoadDone = FALSE;
+UINT32 mMcuLoadCount;
+
+///
+/// Array of pointers which each points to 1 microcode update binary (in memory)
+///
+EFI_CPU_MICROCODE_HEADER **mMicrocodePointerBuffer;
+
+///
+/// Function declarations
+///
+EFI_STATUS
+FindLoadMicrocode (
+ IN UINT32 Cpuid,
+ IN EFI_CPU_MICROCODE_HEADER **MicrocodePointerBuffer,
+ IN OUT UINT32 *Revision
+ );
+
+/**
+ To indicate the first microcode load is done
+**/
+VOID
+McuFirstLoadDone (
+ VOID
+ )
+{
+ mMcuFirstLoadDone = TRUE;
+}
+
+/**
+ Wait till all primary threads done the microcode load
+**/
+VOID
+WaitForPrimaryThreadMcuUpdate (
+ VOID
+ )
+{
+ UINTN CoreNumber;
+ CoreNumber = RShiftU64 (AsmReadMsr64 (MSR_CORE_THREAD_COUNT), 16) & 0xffff;
+ if (IsSecondaryThread ()) {
+ while (mMcuLoadCount < CoreNumber) {
+ CpuPause ();
+ }
+ }
+}
+
+/**
+ This function checks the MCU revision to decide if BIOS needs to load
+ microcode.
+
+ @param[in] MicrocodePointer - Microcode in memory
+ @param[in] Revision - Current CPU microcode revision
+
+ @retval EFI_SUCCESS - BIOS needs to load microcode
+ @retval EFI_ABORTED - Don't need to update microcode
+**/
+EFI_STATUS
+CheckMcuRevision (
+ IN EFI_CPU_MICROCODE_HEADER *MicrocodePointer,
+ IN UINT32 *Revision
+ )
+{
+ EFI_STATUS Status;
+ Status = EFI_ABORTED;
+
+ if (mMcuFirstLoadDone) {
+ if (MicrocodePointer->UpdateRevision & 0x80000000 ||
+ (MicrocodePointer->UpdateRevision > 0 && MicrocodePointer->UpdateRevision > *Revision)
+ ) {
+ Status = EFI_SUCCESS;
+ }
+ } else {
+ if (*Revision == 0) {
+ Status = EFI_SUCCESS;
+ }
+ }
+
+ return Status;
+}
+
+/**
+ This will locate a processor microcode and if it finds a newer revision, it will
+ load it to the processor.
+
+ @param[in] MicrocodePointerBuffer - The Array of pointers which each points to 1 microcode update binary (in memory)
+ @param[in] FailedRevision - The microcode revision that fails to be loaded
+
+ @retval EFI_SUCCESS - A new microcode update is loaded
+ @retval Other - Due to some reason, no new microcode update is loaded
+**/
+EFI_STATUS
+InitializeMicrocode (
+ IN EFI_CPU_MICROCODE_HEADER **MicrocodePointerBuffer,
+ OUT UINT32 *FailedRevision
+ )
+{
+ EFI_STATUS Status;
+ EFI_CPUID_REGISTER Cpuid;
+ UINT32 UcodeRevision;
+
+ AsmCpuid (
+ CPUID_VERSION_INFO,
+ &Cpuid.RegEax,
+ &Cpuid.RegEbx,
+ &Cpuid.RegEcx,
+ &Cpuid.RegEdx
+ );
+
+ WaitForPrimaryThreadMcuUpdate ();
+ UcodeRevision = GetCpuUcodeRevision ();
+ Status = FindLoadMicrocode (
+ Cpuid.RegEax,
+ MicrocodePointerBuffer,
+ &UcodeRevision
+ );
+ *FailedRevision = UcodeRevision;
+
+ InterlockedIncrement (&mMcuLoadCount);
+
+ return Status;
+}
+
+/**
+ This will load the microcode to the processors.
+
+ @param[in] MicrocodeEntryPoint - The microcode update pointer
+ @param[in] Revision - The current (before load this microcode update) microcode revision
+
+ @retval EFI_SUCCESS - Microcode loaded
+ @retval EFI_LOAD_ERROR - Microcode not loaded
+**/
+EFI_STATUS
+LoadMicrocode (
+ IN EFI_CPU_MICROCODE_HEADER *MicrocodeEntryPoint,
+ IN UINT32 *Revision
+ )
+{
+ ///
+ /// Load the Processor Microcode
+ ///
+ AsmWriteMsr64 (
+ MSR_IA32_BIOS_UPDT_TRIG,
+ (UINT64) ((UINTN) MicrocodeEntryPoint + sizeof (EFI_CPU_MICROCODE_HEADER))
+ );
+
+ ///
+ /// Verify that the microcode has been loaded
+ ///
+ if (GetCpuUcodeRevision () == *Revision) {
+ return EFI_LOAD_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Verify the DWORD type checksum
+
+ @param[in] ChecksumAddr - The start address to be checksumed
+ @param[in] ChecksumLen - The length of data that will be checksumed
+
+ @retval EFI_SUCCESS - Checksum correct
+ @retval EFI_CRC_ERROR - Checksum incorrect
+**/
+EFI_STATUS
+Checksum32Verify (
+ IN UINT32 *ChecksumAddr,
+ IN UINT32 ChecksumLen
+ )
+{
+ UINT32 Checksum;
+ UINT32 Index;
+
+ Checksum = 0;
+
+ for (Index = 0; Index < ChecksumLen; Index++) {
+ Checksum += ChecksumAddr[Index];
+ }
+
+ return (Checksum == 0) ? EFI_SUCCESS : EFI_CRC_ERROR;
+}
+
+/**
+ Check if this microcode is correct one for processor
+
+ @param[in] Cpuid - processor CPUID
+ @param[in] MicrocodeEntryPoint - entry point of microcode
+ @param[in] Revision - revision of microcode
+
+ @retval CorrectMicrocode if this microcode is correct
+**/
+BOOLEAN
+CheckMicrocode (
+ IN UINTN Cpuid,
+ IN EFI_CPU_MICROCODE_HEADER *MicrocodeEntryPoint,
+ IN UINT32 *Revision
+ )
+{
+ EFI_STATUS Status;
+ UINT8 ExtendedIndex;
+ UINT8 MsrPlatform;
+ UINT32 ExtendedTableLength;
+ UINT32 ExtendedTableCount;
+ BOOLEAN CorrectMicrocode;
+ EFI_CPU_MICROCODE_EXTENDED_TABLE *ExtendedTable;
+ EFI_CPU_MICROCODE_EXTENDED_TABLE_HEADER *ExtendedTableHeader;
+
+ Status = EFI_NOT_FOUND;
+ ExtendedTableLength = 0;
+ CorrectMicrocode = FALSE;
+
+ ///
+ /// The index of platform information resides in bits 50:52 of MSR IA32_PLATFORM_ID
+ ///
+ MsrPlatform = (UINT8) (RShiftU64 (AsmReadMsr64 (MSR_IA32_PLATFORM_ID), 50) & 0x07);
+
+ ///
+ /// Check if the microcode is for the Cpu and the version is newer
+ /// and the update can be processed on the platform
+ ///
+ if ((MicrocodeEntryPoint->HeaderVersion == 0x00000001) &&
+ !EFI_ERROR (CheckMcuRevision (MicrocodeEntryPoint, Revision))
+ ) {
+ if ((MicrocodeEntryPoint->ProcessorId == Cpuid) && (MicrocodeEntryPoint->ProcessorFlags & (1 << MsrPlatform))) {
+ if (MicrocodeEntryPoint->DataSize == 0) {
+ Status = Checksum32Verify ((UINT32 *) MicrocodeEntryPoint, 2048 / sizeof (UINT32));
+ } else {
+ Status = Checksum32Verify (
+ (UINT32 *) MicrocodeEntryPoint,
+ (MicrocodeEntryPoint->DataSize + sizeof (EFI_CPU_MICROCODE_HEADER)) / sizeof (UINT32)
+ );
+ }
+
+ if (!EFI_ERROR (Status)) {
+ CorrectMicrocode = TRUE;
+ }
+ } else if ((MicrocodeEntryPoint->DataSize != 0)) {
+ ///
+ /// Check the Extended Signature if the entended signature exist
+ /// Only the data size != 0 the extended signature may exist
+ ///
+ ExtendedTableLength = MicrocodeEntryPoint->TotalSize - (MicrocodeEntryPoint->DataSize + sizeof (EFI_CPU_MICROCODE_HEADER));
+ if (ExtendedTableLength != 0) {
+ ///
+ /// Extended Table exist, check if the CPU in support list
+ ///
+ ExtendedTableHeader = (EFI_CPU_MICROCODE_EXTENDED_TABLE_HEADER *) ((UINT8 *) (MicrocodeEntryPoint) + MicrocodeEntryPoint->DataSize + 48);
+ ///
+ /// Calulate Extended Checksum
+ ///
+ if ((ExtendedTableLength % 4) == 0) {
+ Status = Checksum32Verify ((UINT32 *) ExtendedTableHeader, ExtendedTableLength / sizeof (UINT32));
+ if (!EFI_ERROR (Status)) {
+ ///
+ /// Checksum correct
+ ///
+ ExtendedTableCount = ExtendedTableHeader->ExtendedSignatureCount;
+ ExtendedTable = (EFI_CPU_MICROCODE_EXTENDED_TABLE *) (ExtendedTableHeader + 1);
+ for (ExtendedIndex = 0; ExtendedIndex < ExtendedTableCount; ExtendedIndex++) {
+ ///
+ /// Verify Header
+ ///
+ if ((ExtendedTable->ProcessorSignature == Cpuid) && (ExtendedTable->ProcessorFlag & (1 << MsrPlatform))) {
+ Status = Checksum32Verify (
+ (UINT32 *) ExtendedTable,
+ sizeof (EFI_CPU_MICROCODE_EXTENDED_TABLE) / sizeof (UINT32)
+ );
+ if (!EFI_ERROR (Status)) {
+ ///
+ /// Find one
+ ///
+ CorrectMicrocode = TRUE;
+ break;
+ }
+ }
+
+ ExtendedTable++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return CorrectMicrocode;
+}
+
+/**
+ Find microcode data
+
+ @param[in] Cpuid - processor CPUID
+ @param[in] MicrocodePointerBuffer - the pointer for microcode buffer
+ @param[in] Revision - revision of microcode
+
+ @retval The pointer of microcode header
+**/
+EFI_CPU_MICROCODE_HEADER *
+FindMicrocode (
+ IN UINTN Cpuid,
+ IN EFI_CPU_MICROCODE_HEADER **MicrocodePointerBuffer,
+ IN UINT32 *Revision
+ )
+{
+ EFI_STATUS Status;
+ EFI_CPU_MICROCODE_HEADER *MicrocodeEntryPoint;
+ UINT8 Index;
+ BOOLEAN CorrectMicrocode;
+
+ Status = EFI_NOT_FOUND;
+ MicrocodeEntryPoint = NULL;
+ CorrectMicrocode = FALSE;
+
+ Index = 0;
+ while (MicrocodePointerBuffer[Index] != NULL) {
+ MicrocodeEntryPoint = MicrocodePointerBuffer[Index];
+ CorrectMicrocode = CheckMicrocode (Cpuid, MicrocodeEntryPoint, Revision);
+
+ if (CorrectMicrocode) {
+ break;
+ }
+
+ Index++;
+ }
+
+ if (!CorrectMicrocode) {
+ MicrocodeEntryPoint = NULL;
+ }
+
+ return MicrocodeEntryPoint;
+}
+
+/**
+ This will locate a processor microcode and if it finds a newer revision, it will
+ load it to the processor.
+
+ @param[in] Cpuid - Data returned by cpuid instruction
+ @param[in] MicrocodePointerBuffer - The Array of pointers which each points to 1 microcode update binary (in memory)
+ @param[in] Revision - As input parameter, the current microcode revision;
+ as output parameter, the microcode revision after microcode update is loaded
+
+ @retval EFI_SUCCESS - A new microcode update is loaded
+ @retval Other - Due to some reason, no new microcode update is loaded
+**/
+EFI_STATUS
+FindLoadMicrocode (
+ IN UINT32 Cpuid,
+ IN EFI_CPU_MICROCODE_HEADER **MicrocodePointerBuffer,
+ IN OUT UINT32 *Revision
+ )
+{
+ EFI_STATUS Status;
+ EFI_CPU_MICROCODE_HEADER *MicrocodeEntryPoint;
+
+ Status = EFI_NOT_FOUND;
+
+ MicrocodeEntryPoint = FindMicrocode (
+ Cpuid,
+ MicrocodePointerBuffer,
+ Revision
+ );
+
+ if (MicrocodeEntryPoint != NULL) {
+ Status = LoadMicrocode (MicrocodeEntryPoint, Revision);
+ *Revision = MicrocodeEntryPoint->UpdateRevision;
+ }
+
+ return Status;
+}
+
+/**
+ Load all microcode updates to memory. Since in S3 resume boot path, CPUs should be
+ patched again, these microcode updates are copied to OS reserved memory.
+
+ @retval EFI_SUCCESS - All microcode updates are loaded to memory successfully
+ @retval EFI_OUT_OF_RESOURCES - Not enough memory to accomodate all the microcode updates
+**/
+EFI_STATUS
+LoadAllMicrocodeUpdates (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_CPU_MICROCODE_HEADER *MicrocodeEntryPoint;
+ EFI_CPU_MICROCODE_HEADER *MicrocodeBuffer;
+ UINTN MicrocodeNumber;
+ UINTN Index;
+ UINTN TotalSize[NUMBER_OF_MICROCODE_UPDATE + 1];
+ EFI_CPUID_REGISTER Cpuid;
+ UINT32 UcodeRevision;
+
+ AsmCpuid (
+ CPUID_VERSION_INFO,
+ &Cpuid.RegEax,
+ &Cpuid.RegEbx,
+ &Cpuid.RegEcx,
+ &Cpuid.RegEdx
+ );
+
+ UcodeRevision = 0;
+ MicrocodeNumber = 0;
+ Status = (gBS->AllocatePool)
+ (
+ EfiReservedMemoryType, sizeof (EFI_CPU_MICROCODE_HEADER *) * (NUMBER_OF_MICROCODE_UPDATE + 1), (VOID *)
+ (&mMicrocodePointerBuffer)
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ZeroMem (mMicrocodePointerBuffer, sizeof (EFI_CPU_MICROCODE_HEADER *) * (NUMBER_OF_MICROCODE_UPDATE + 1));
+
+ MicrocodeEntryPoint = NULL;
+ while (TRUE) {
+ if (MicrocodeNumber > NUMBER_OF_MICROCODE_UPDATE) {
+ DEBUG ((EFI_D_INFO, "CPU Too Many Microcode available > %d\n", (UINTN) NUMBER_OF_MICROCODE_UPDATE));
+ Status = EFI_SUCCESS;
+ break;
+ }
+ ///
+ /// Initialize it to 0
+ ///
+ TotalSize[MicrocodeNumber] = 0;
+ ///
+ /// Continue to try to find patch
+ ///
+ Status = mPlatformCpu->CpuConfig->RetrieveMicrocode (mPlatformCpu, (VOID *) &MicrocodeEntryPoint);
+
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_NOT_FOUND) {
+ Status = EFI_SUCCESS;
+ }
+ break;
+
+ } else {
+ if (!CheckMicrocode (Cpuid.RegEax, MicrocodeEntryPoint, &UcodeRevision)) {
+ continue;
+ }
+
+ if (MicrocodeEntryPoint->DataSize == 0) {
+ TotalSize[MicrocodeNumber] = 2048;
+ } else {
+ TotalSize[MicrocodeNumber] = MicrocodeEntryPoint->TotalSize;
+ }
+
+ Status = AllocateReservedMemoryBelow4G (
+ TotalSize[MicrocodeNumber],
+ &MicrocodeBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ CopyMem (MicrocodeBuffer, MicrocodeEntryPoint, TotalSize[MicrocodeNumber]);
+ mMicrocodePointerBuffer[MicrocodeNumber] = MicrocodeBuffer;
+ MicrocodeNumber++;
+ }
+ }
+
+ if (EFI_ERROR (Status)) {
+ Index = 0;
+ while ((Index <= NUMBER_OF_MICROCODE_UPDATE) && (mMicrocodePointerBuffer[Index] != NULL)) {
+ (gBS->FreePages)((EFI_PHYSICAL_ADDRESS) (UINTN) mMicrocodePointerBuffer[Index], EFI_SIZE_TO_PAGES (TotalSize[Index]));
+ mMicrocodePointerBuffer[Index] = NULL;
+ Index++;
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Check if loading microcode update fails, if so, report proper status code
+
+ @param[in] CpuNumber - The CPU number
+ @param[in] Status - The return value of InitializeMicrocode()
+ @param[in] FailedRevision - The revision of the microcode update that failed to be loaded
+
+ @retval EFI_SUCCESS - The status is check and proper status code is reported
+**/
+EFI_STATUS
+CheckMicrocodeUpdate (
+ IN UINTN CpuNumber,
+ IN EFI_STATUS Status,
+ IN UINT32 FailedRevision
+ )
+{
+ EFI_STATUS_CODE_VALUE StatusCode;
+
+ if (!EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ }
+ if (Status == EFI_LOAD_ERROR) {
+ StatusCode = EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_EC_MICROCODE_UPDATE;
+ } else if (Status == EFI_NOT_FOUND) {
+ if (GetCpuUcodeRevision () != 0) {
+ ///
+ /// Some other driver (for example, SEC) already updated CPU microcode
+ ///
+ return EFI_SUCCESS;
+ }
+ StatusCode = EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_EC_NO_MICROCODE_UPDATE;
+ } else {
+ return Status;
+ }
+ ///
+ /// ReportStatusCode UEFI service can't be called by AP currently, so call by BSP only
+ ///
+ if (CpuNumber == mMPSystemData->BSP) {
+ return ReportStatusCode (
+ EFI_ERROR_MINOR | EFI_ERROR_CODE,
+ StatusCode
+ );
+ } else {
+ return Status;
+ }
+}
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/MpCommon.c b/ReferenceCode/Haswell/CpuInit/Dxe/MpCommon.c
new file mode 100644
index 0000000..dd9a55e
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/MpCommon.c
@@ -0,0 +1,1186 @@
+/** @file
+ Code which support multi-processor
+
+@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 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
+
+**/
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "MpCommon.h"
+#include "CpuInitDxe.h"
+#include "Features.h"
+#include EFI_PROTOCOL_DEFINITION (ExitPmAuth)
+#endif
+
+extern MP_SYSTEM_DATA *mMPSystemData;
+
+extern EFI_PHYSICAL_ADDRESS mOriginalBuffer;
+extern EFI_PHYSICAL_ADDRESS mBackupBuffer;
+extern EFI_METRONOME_ARCH_PROTOCOL *mMetronome;
+extern DXE_CPU_PLATFORM_POLICY_PROTOCOL *mPlatformCpu;
+volatile UINTN mSwitchToLegacyRegionCount = 0;
+
+EFI_PHYSICAL_ADDRESS mLegacyRegion;
+//(AMI_CHG+)>
+#if (REQUEST_EBDA_SIZE != 0x1000)
+UINTN mEbdaOffset = 0;
+#endif
+//<(AMI_CHG+)
+
+/**
+ Check if X2APIC is enabled
+
+ @retval TRUE if enabled
+ @retval FALSE if not enabled
+**/
+BOOLEAN
+IsXapicEnabled (
+ VOID
+ )
+{
+ UINT64 MsrValue;
+
+ MsrValue = AsmReadMsr64 (MSR_IA32_APIC_BASE);
+ if (MsrValue & B_MSR_IA32_APIC_BASE_G_XAPIC) {
+ if (MsrValue & B_MSR_IA32_APIC_BASE_M_XAPIC) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ Function to get APIC register from MSR or MMIO
+
+ @param[in] XapicEnabled - x2APIC enabled or not
+ @param[in] MsrIndex - MSR index of APIC register
+ @param[in] MemoryMappedIo - MMIO address for APIC register
+
+ @retval The value of APIC register
+**/
+UINT64
+ReadApicMsrOrMemory (
+ BOOLEAN XapicEnabled,
+ UINT32 MsrIndex,
+ UINT64 MemoryMappedIo
+ )
+{
+ UINT64 Value;
+
+ if (XapicEnabled) {
+ Value = AsmReadMsr64 (MsrIndex);
+ } else {
+ Value = (UINT64) *(volatile UINT32 *) (UINTN) MemoryMappedIo;
+ }
+
+ return Value;
+}
+
+/**
+ Function to write APIC register by MSR or MMIO
+
+ @param[in] XapicEnabled - x2APIC enabled or not
+ @param[in] MsrIndex - MSR index of APIC register
+ @param[in] MemoryMappedIo - MMIO address for APIC register
+ @param[in] Value - Value that will be written to APIC register
+**/
+VOID
+WriteApicMsrOrMemory (
+ BOOLEAN XapicEnabled,
+ UINT32 MsrIndex,
+ UINT64 MemoryMappedIo,
+ UINT64 Value
+ )
+{
+ if (XapicEnabled) {
+ AsmWriteMsr64 (MsrIndex, Value);
+ } else {
+ if (MsrIndex == EXT_XAPIC_ICR) {
+ *(volatile UINT32 *) (UINTN) (MemoryMappedIo - APIC_REGISTER_ICR_LOW_OFFSET + APIC_REGISTER_ICR_HIGH_OFFSET) = (UINT32) (Value >> 32);
+ }
+ *(volatile UINT32 *) (UINTN) MemoryMappedIo = (UINT32) Value;
+ }
+}
+
+/**
+ Send interrupt to CPU
+
+ @param[in] BroadcastMode - Interrupt broadcast mode
+ @param[in] ApicID - APIC ID for sending interrupt
+ @param[in] VectorNumber - Vector number
+ @param[in] DeliveryMode - Interrupt delivery mode
+ @param[in] TriggerMode - Interrupt trigger mode
+ @param[in] Assert - Interrupt pin polarity
+
+ @retval EFI_INVALID_PARAMETER - Input parameter not correct
+ @retval EFI_NOT_READY - There was a pending interrupt
+ @retval EFI_SUCCESS - Interrupt sent successfully
+**/
+EFI_STATUS
+SendInterrupt (
+ IN UINT32 BroadcastMode,
+ IN UINT32 ApicID,
+ IN UINT32 VectorNumber,
+ IN UINT32 DeliveryMode,
+ IN UINT32 TriggerMode,
+ IN BOOLEAN Assert
+ )
+{
+ UINT64 ApicBaseReg;
+ EFI_PHYSICAL_ADDRESS ApicBase;
+ UINT32 ICRLow;
+ UINT32 ICRHigh;
+ BOOLEAN XapicEnabled;
+
+ ///
+ /// Initialze ICR high dword, since P6 family processor needs
+ /// the destination field to be 0x0F when it is a broadcast
+ ///
+ ICRHigh = 0x0f000000;
+ ICRLow = VectorNumber | (DeliveryMode << 8);
+
+ if (TriggerMode == TRIGGER_MODE_LEVEL) {
+ ICRLow |= 0x8000;
+ }
+
+ if (Assert) {
+ ICRLow |= 0x4000;
+ }
+
+ XapicEnabled = IsXapicEnabled ();
+
+ switch (BroadcastMode) {
+ case BROADCAST_MODE_SPECIFY_CPU:
+ if (XapicEnabled) {
+ ICRHigh = (UINT32) ApicID;
+ } else {
+ ICRHigh = ApicID << 24;
+ }
+ break;
+
+ case BROADCAST_MODE_ALL_INCLUDING_SELF:
+ ICRLow |= 0x80000;
+ break;
+
+ case BROADCAST_MODE_ALL_EXCLUDING_SELF:
+ ICRLow |= 0xC0000;
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ApicBaseReg = AsmReadMsr64 (MSR_IA32_APIC_BASE);
+ ApicBase = ApicBaseReg & 0xffffff000;
+
+ ///
+ /// According Nehalem BWG, if Extended XAPIC Mode is enabled,
+ /// legacy xAPIC is no longer working.
+ /// So, previous MMIO offset must be transferred to MSR offset R/W.
+ /// ----------------------------------------------------------------
+ /// MMIO Offset MSR Offset Register Name
+ /// ----------------------------------------------------------------
+ /// 300h-310h 830h Interrupt Command Register [63:0]
+ /// 831h [Reserved]
+ /// ----------------------------------------------------------------
+ ///
+ WriteApicMsrOrMemory (
+ XapicEnabled,
+ EXT_XAPIC_ICR,
+ ApicBase + APIC_REGISTER_ICR_LOW_OFFSET,
+ (((UINT64) ICRHigh << 32) | (UINT64) ICRLow)
+ );
+
+ gBS->Stall (10);
+
+ ICRLow = (UINT32) ReadApicMsrOrMemory (XapicEnabled, EXT_XAPIC_ICR, ApicBase + APIC_REGISTER_ICR_LOW_OFFSET);
+
+ if (ICRLow & BIT12) {
+ return EFI_NOT_READY;
+ }
+
+ gBS->Stall (100);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Check number of cores in the package.
+
+ @retval Number of cores in the package.
+**/
+UINT8
+GetCoreNumber (
+ VOID
+ )
+{
+ EFI_CPUID_REGISTER Cpuid;
+ AsmCpuidEx (
+ 4,
+ 0,
+ &Cpuid.RegEax,
+ NULL,
+ NULL,
+ NULL
+ );
+ return (UINT8)(RShiftU64 (Cpuid.RegEax, 26) & 0x3f) + 1;
+}
+
+/**
+ Get APIC ID of processor
+
+ @param[in] ApicBase - APIC base
+ @param[in] ApicVersion - APIC version
+
+ @retval APIC ID of processor
+**/
+UINT32
+GetApicID (
+ OUT EFI_PHYSICAL_ADDRESS *ApicBase OPTIONAL,
+ OUT UINT32 *ApicVersion OPTIONAL
+ )
+{
+ UINT64 ApicBaseReg;
+ UINT32 ApicID;
+ UINT32 LocalApicVersion;
+ UINT64 LocalApicBase;
+ UINTN MsrValue;
+ BOOLEAN XapicEnabled;
+
+ XapicEnabled = IsXapicEnabled ();
+
+ if (XapicEnabled) {
+ ///
+ /// According Nehalem BWG, if Extended XAPIC Mode
+ /// is enabled, legacy xAPIC is no longer working.
+ /// So, previous MMIO offset must be transfered
+ /// to MSR offset R/W.
+ /// MMIO Offset MSR Offset Register Name
+ /// 020h 802h EXT_XAPIC_LOGICAL_APIC_ID
+ /// 030h 803h EXT_XAPIC_VERSION
+ ///
+ MsrValue = (UINTN) AsmReadMsr64 (EXT_XAPIC_VERSION);
+ *ApicVersion = (UINT32) (MsrValue & 0xff);
+ *ApicBase = 0;
+
+ MsrValue = (UINTN) AsmReadMsr64 (EXT_XAPIC_LOGICAL_APIC_ID);
+ ApicID = (UINT32) MsrValue;
+ return ApicID;
+ }
+
+ ApicBaseReg = AsmReadMsr64 (MSR_IA32_APIC_BASE);
+ LocalApicBase = ApicBaseReg & 0xffffff000;
+ if (ApicBase) {
+ *ApicBase = LocalApicBase;
+ }
+
+ ///
+ /// if Apic is not enabled yet, enable it here
+ ///
+ if ((ApicBaseReg & 0x800) == 0) {
+ ApicBaseReg |= 0x800;
+ AsmWriteMsr64 (MSR_IA32_APIC_BASE, ApicBaseReg);
+ }
+
+ if (ApicVersion) {
+ LocalApicVersion = *(volatile UINT32 *) (UINTN) (LocalApicBase + APIC_REGISTER_APIC_VERSION_OFFSET);
+ *ApicVersion = LocalApicVersion & 0xff;
+ }
+
+ ApicID = *(volatile UINT32 *) (UINTN) (LocalApicBase + APIC_REGISTER_LOCAL_ID_OFFSET);
+ return (ApicID >> 24) & 0x0ff;
+}
+
+/**
+ Programs Local APIC registers.
+
+ @param[in] BSP - Is this BSP?
+**/
+VOID
+ProgramXApic (
+ BOOLEAN BSP
+ )
+{
+ UINT64 ApicBaseReg;
+ EFI_PHYSICAL_ADDRESS ApicBase;
+ UINT64 EntryValue;
+ BOOLEAN XapicEnabled;
+
+ ApicBaseReg = AsmReadMsr64 (MSR_IA32_APIC_BASE);
+ ApicBase = ApicBaseReg & 0xffffff000;
+
+ XapicEnabled = IsXapicEnabled ();
+
+ ///
+ /// Program the Spurious Vector entry if XAPIC is enabled
+ ///
+ EntryValue = ReadApicMsrOrMemory (XapicEnabled, EXT_XAPIC_SVR, ApicBase + APIC_REGISTER_SPURIOUS_VECTOR_OFFSET);
+ EntryValue &= 0xFFFFFD0F;
+ EntryValue |= 0x10F;
+ WriteApicMsrOrMemory (XapicEnabled, EXT_XAPIC_SVR, ApicBase + APIC_REGISTER_SPURIOUS_VECTOR_OFFSET, EntryValue);
+
+ ///
+ /// Double check if it is BSP
+ ///
+ if (!BSP) {
+ CpuDisableInterrupt ();
+ }
+
+ ///
+ /// Program the LINT0 vector entry as EntInt
+ ///
+ EntryValue = ReadApicMsrOrMemory (XapicEnabled, EXT_XAPIC_LVT_LINT0, ApicBase + APIC_REGISTER_LINT0_VECTOR_OFFSET);
+ if (BSP) {
+ EntryValue &= 0xFFFE00FF;
+ EntryValue |= 0x700;
+ } else {
+ EntryValue |= 0x10000;
+ ///
+ /// set bit 16 as mask for LINT0
+ ///
+ }
+
+ WriteApicMsrOrMemory (XapicEnabled, EXT_XAPIC_LVT_LINT0, ApicBase + APIC_REGISTER_LINT0_VECTOR_OFFSET, EntryValue);
+
+ ///
+ /// Program the LINT1 vector entry as NMI
+ ///
+ EntryValue = ReadApicMsrOrMemory (XapicEnabled, EXT_XAPIC_LVT_LINT1, ApicBase + APIC_REGISTER_LINT1_VECTOR_OFFSET);
+ EntryValue &= 0xFFFE00FF;
+ if (BSP) {
+ EntryValue |= 0x400;
+ } else {
+ EntryValue |= 0x10400;
+ }
+
+ WriteApicMsrOrMemory (XapicEnabled, EXT_XAPIC_LVT_LINT1, ApicBase + APIC_REGISTER_LINT1_VECTOR_OFFSET, EntryValue);
+
+}
+
+/**
+ Allocate a temporary memory under 1MB for MP Init to perform INIT-SIPI.
+ This buffer also provides memory for stack/data for MP running
+
+ @param[in] WakeUpBuffer - Return buffer location
+
+ @retval EFI_SUCCESS if ok to get a memory under 1MB for MP running.
+**/
+EFI_STATUS
+AllocateWakeUpBuffer (
+ OUT EFI_PHYSICAL_ADDRESS *WakeUpBuffer
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ for (*WakeUpBuffer = 0x58000; *WakeUpBuffer >= 0x2000; *WakeUpBuffer -= 0x1000) {
+ Status = (gBS->AllocatePages)(AllocateAddress, EfiReservedMemoryType, 1, WakeUpBuffer);
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Allocate Reserved Memory
+
+ @param[in] Size - Memory Size
+ @param[in] Alignment - Alignment size
+ @param[in] Pointer - return memory location
+
+ @retval EFI_SUCCESS - Allocate a reserved memory successfully
+**/
+EFI_STATUS
+AllocateAlignedReservedMemory (
+ IN UINTN Size,
+ IN UINTN Alignment,
+ OUT VOID **Pointer
+ )
+{
+ EFI_STATUS Status;
+ UINTN PointerValue;
+
+ Status = AllocateReservedMemoryBelow4G (
+ Size + Alignment - 1,
+ Pointer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ PointerValue = (UINTN) *Pointer;
+ PointerValue = (PointerValue + Alignment - 1) / Alignment * Alignment;
+
+ *Pointer = (VOID *) PointerValue;
+ return EFI_SUCCESS;
+}
+
+/**
+ Fill in the CPU location information
+
+ @param[in] Location - CPU location information
+
+ @retval EFI_SUCCESS - always return success
+**/
+EFI_STATUS
+FillInCpuLocation (
+ IN CPU_PHYSICAL_LOCATION *Location
+ )
+{
+ UINT32 ApicId;
+ EFI_CPUID_REGISTER RegsInfo;
+ UINT32 LevelType;
+ UINT32 LevelBits;
+ UINT8 Shift;
+ UINT8 Bits;
+ UINT32 Mask;
+ BOOLEAN HyperThreadingEnabled;
+
+ AsmCpuid (CPUID_VERSION_INFO, &RegsInfo.RegEax, &RegsInfo.RegEbx, &RegsInfo.RegEcx, &RegsInfo.RegEdx);
+ ApicId = (RegsInfo.RegEbx >> 24);
+
+ AsmCpuid (CPUID_SIGNATURE, &RegsInfo.RegEax, &RegsInfo.RegEbx, &RegsInfo.RegEcx, &RegsInfo.RegEdx);
+ if (RegsInfo.RegEax >= CPUID_CORE_TOPOLOGY) {
+ LevelBits = 0;
+ LevelType = 0;
+ do {
+ AsmCpuidEx (
+ CPUID_CORE_TOPOLOGY,
+ LevelType,
+ &RegsInfo.RegEax,
+ &RegsInfo.RegEbx,
+ &RegsInfo.RegEcx,
+ &RegsInfo.RegEdx
+ );
+ LevelType = ((RegsInfo.RegEcx >> 8) & 0xFF);
+ switch (LevelType) {
+ case 1:
+ ///
+ /// Thread
+ ///
+ Location->Thread = ApicId & ((1 << (RegsInfo.RegEax & 0x0F)) - 1);
+ LevelBits = RegsInfo.RegEax & 0x0F;
+ break;
+
+ case 2:
+ ///
+ /// Core
+ ///
+ Location->Core = ApicId >> LevelBits;
+ LevelBits = RegsInfo.RegEax & 0x0F;
+ break;
+
+ default:
+ ///
+ /// End of Level
+ ///
+ Location->Die = 0;
+ Location->Package = ApicId >> LevelBits;
+ break;
+ }
+ } while (!(RegsInfo.RegEax == 0 && RegsInfo.RegEbx == 0));
+ } else {
+
+ AsmCpuid (CPUID_VERSION_INFO, &RegsInfo.RegEax, &RegsInfo.RegEbx, &RegsInfo.RegEcx, &RegsInfo.RegEdx);
+ Bits = 0;
+ Shift = (UINT8) ((RegsInfo.RegEbx >> 16) & 0xFF);
+
+ Mask = Shift - 1;
+ while (Shift > 1) {
+ Shift >>= 1;
+ Bits++;
+ }
+
+ HyperThreadingEnabled = FALSE;
+ AsmCpuidEx (CPUID_CACHE_PARAMS, 0, &RegsInfo.RegEax, &RegsInfo.RegEbx, &RegsInfo.RegEcx, &RegsInfo.RegEdx);
+ if (Mask > (RegsInfo.RegEax >> 26)) {
+ HyperThreadingEnabled = TRUE;
+ }
+
+ Location->Package = (ApicId >> Bits);
+ Location->Die = 0;
+ if (HyperThreadingEnabled) {
+ Location->Core = (ApicId & Mask) >> 1;
+ Location->Thread = (ApicId & Mask) & 1;
+ } else {
+ Location->Core = (ApicId & Mask);
+ Location->Thread = 0;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Fill in CPU relevant information into data hub
+
+ @param[in] CpuNumber - CPU number
+ @param[in] CpuDataforDatahub - pointer to data hub that will be updated
+
+ @retval EFI_SUCCESS - always return success
+**/
+EFI_STATUS
+FillinDataforDataHub (
+ IN UINTN CpuNumber,
+ OUT CPU_DATA_FOR_DATAHUB *CpuDataforDatahub
+ )
+{
+ ZeroMem (CpuDataforDatahub, sizeof (*CpuDataforDatahub));
+
+ ///
+ /// Read Cpu Frequency from MSR instead
+ ///
+ CpuDataforDatahub->IntendCoreFrequency =
+ (
+ 100 *
+ (((UINT32) EfiReadMsr (MSR_IA32_PERF_STS) >> N_IA32_PERF_STSP_STATE_TARGET) & B_IA32_PERF_STSP_STATE_MASK)
+ );
+
+ GetProcessorVersion (&CpuDataforDatahub->Version);
+ CpuDataforDatahub->Manufacturer = GetProcessorManufacturer ();
+
+ EfiCpuid (CPUID_VERSION_INFO, (EFI_CPUID_REGISTER *) &CpuDataforDatahub->CpuidData);
+
+ CpuDataforDatahub->Family = GetProcessorFamily ();
+ CpuDataforDatahub->Voltage = GetProcessorVoltage ();
+ CpuDataforDatahub->ApicID = GetApicID (
+ &CpuDataforDatahub->ApicBase,
+ &CpuDataforDatahub->ApicVersion
+ );
+
+ CpuDataforDatahub->MicrocodeRevision = GetCpuUcodeRevision ();
+ EfiCpuid (CPUID_CACHE_INFO, CpuDataforDatahub->CacheInformation);
+
+ ///
+ /// Status field will be updated later, after calling CpuPlatformPolicy protocol to override
+ ///
+ CpuDataforDatahub->Status = GetProcessorStatus (CpuNumber);;
+
+ FillInCpuLocation (&CpuDataforDatahub->Location);
+
+ ///
+ /// Health field will be filled in else where
+ ///
+ return EFI_SUCCESS;
+}
+
+/**
+ Allocate EfiReservedMemoryType below 4G memory address.
+
+ @param[in] Size - Size of memory to allocate.
+ @param[in] Buffer - Allocated address for output.
+
+ @retval EFI_SUCCESS - Memory successfully allocated.
+ @retval Other - Other errors occur.
+**/
+EFI_STATUS
+AllocateReservedMemoryBelow4G (
+ IN UINTN Size,
+ OUT VOID **Buffer
+ )
+{
+ UINTN Pages;
+ EFI_PHYSICAL_ADDRESS Address;
+ EFI_STATUS Status;
+
+ Pages = EFI_SIZE_TO_PAGES (Size);
+ Address = 0xffffffff;
+
+ Status = (gBS->AllocatePages)(AllocateMaxAddress, EfiReservedMemoryType, Pages, &Address);
+
+ *Buffer = (VOID *) (UINTN) Address;
+
+ return Status;
+}
+
+/**
+ This function is invoked when SMM_BASE protocol is installed, then we
+ allocate SMRAM and save all information there.
+
+ @param[in] Event - The triggered event.
+ @param[in] Context - Context for this event.
+**/
+VOID
+EFIAPI
+InitializeSmramDataContent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_SMM_BASE_PROTOCOL *SmmBase;
+ SMRAM_CPU_DATA SmramCpuDataTemplate;
+ UINTN LockBoxSize;
+ UINT8 *LockBoxData;
+ PSEUDO_DESCRIPTOR *Idtr;
+ PSEUDO_DESCRIPTOR *Gdtr;
+ UINTN MicrocodeSize;
+ EFI_CPU_MICROCODE_HEADER **Microcode;
+ UINT8 *LockBoxMicrocode;
+ UINTN Index;
+ EFI_STATUS Status;
+ EFI_SMM_CONTROL_PROTOCOL *SmmControl;
+ UINT8 *SmramCpuData;
+ UINTN VarSize;
+ SMRAM_CPU_DATA_ADDRESS SmramCpuDataAddr;
+ UINTN ArgBufferSize;
+ UINT8 ArgBuffer;
+ EFI_SMM_CONTROL_REGISTER SmiRegister;
+
+ DEBUG ((EFI_D_INFO, "InitializeSmramDataContent\n"));
+
+ Status = gBS->LocateProtocol (&gEfiSmmBaseProtocolGuid, NULL, (VOID **) &SmmBase);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->LocateProtocol (&gEfiSmmControlProtocolGuid, NULL, (VOID **) &SmmControl);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Init
+ ///
+ CopyMem (&SmramCpuDataTemplate.HeaderGuid, &gSmramCpuDataHeaderGuid, sizeof (EFI_GUID));
+ SmramCpuDataTemplate.AcpiCpuPointer = (EFI_PHYSICAL_ADDRESS) (UINTN) mAcpiCpuData;
+ CopyMem (&SmramCpuDataTemplate.AcpiCpuData, mAcpiCpuData, sizeof (ACPI_CPU_DATA));
+
+ ///
+ /// Calculate size
+ ///
+ SmramCpuDataTemplate.GdtrProfileSize = sizeof (PSEUDO_DESCRIPTOR);
+ Gdtr = (PSEUDO_DESCRIPTOR *) (UINTN) mAcpiCpuData->GdtrProfile;
+ SmramCpuDataTemplate.GdtSize = Gdtr->Limit + 1;
+ SmramCpuDataTemplate.IdtrProfileSize = sizeof (PSEUDO_DESCRIPTOR);
+ Idtr = (PSEUDO_DESCRIPTOR *) (UINTN) mAcpiCpuData->GdtrProfile;
+ SmramCpuDataTemplate.IdtSize = Idtr->Limit + 1;
+ SmramCpuDataTemplate.CpuPrivateDataSize = sizeof (MP_CPU_S3_DATA_POINTER);
+ SmramCpuDataTemplate.S3BootScriptTableSize = sizeof (mMPSystemData->S3BootScriptTable);
+ SmramCpuDataTemplate.S3BspMtrrTableSize = sizeof (mMPSystemData->S3BspMtrrTable);
+ ///
+ /// Record best match for each CPU Microcode and NULL for end
+ ///
+ SmramCpuDataTemplate.MicrocodePointerBufferSize = sizeof (UINT32) * (mAcpiCpuData->NumberOfCpus + 1);
+ ///
+ /// Calculate Microcode DataSize
+ ///
+ SmramCpuDataTemplate.MicrocodeDataBufferSize = 0;
+ Microcode = (VOID *) (UINTN) mAcpiCpuData->MicrocodePointerBuffer;
+ if (Microcode != NULL) {
+ Index = 0;
+ MicrocodeSize = 0;
+ while (Microcode[Index] != NULL) {
+ if (Microcode[Index]->DataSize == 0) {
+ MicrocodeSize = 2048;
+ } else {
+ MicrocodeSize = Microcode[Index]->TotalSize;
+ }
+
+ SmramCpuDataTemplate.MicrocodeDataBufferSize += (UINT32) MicrocodeSize;
+ Index++;
+ }
+ }
+
+ SmramCpuDataTemplate.GdtrProfileOffset = sizeof (SMRAM_CPU_DATA);
+ SmramCpuDataTemplate.GdtOffset = SmramCpuDataTemplate.GdtrProfileOffset + SmramCpuDataTemplate.GdtrProfileSize;
+ SmramCpuDataTemplate.IdtrProfileOffset = SmramCpuDataTemplate.GdtOffset + SmramCpuDataTemplate.GdtSize;
+ SmramCpuDataTemplate.IdtOffset = SmramCpuDataTemplate.IdtrProfileOffset + SmramCpuDataTemplate.IdtrProfileSize;
+ SmramCpuDataTemplate.CpuPrivateDataOffset = SmramCpuDataTemplate.IdtOffset + SmramCpuDataTemplate.IdtSize;
+ SmramCpuDataTemplate.S3BootScriptTableOffset = SmramCpuDataTemplate.CpuPrivateDataOffset + SmramCpuDataTemplate.CpuPrivateDataSize;
+ SmramCpuDataTemplate.S3BspMtrrTableOffset = SmramCpuDataTemplate.S3BootScriptTableOffset + SmramCpuDataTemplate.S3BootScriptTableSize;
+ SmramCpuDataTemplate.MicrocodePointerBufferOffset = SmramCpuDataTemplate.S3BspMtrrTableOffset + SmramCpuDataTemplate.S3BspMtrrTableSize;
+ SmramCpuDataTemplate.MicrocodeDataBufferOffset = SmramCpuDataTemplate.MicrocodePointerBufferOffset + SmramCpuDataTemplate.MicrocodePointerBufferSize;
+
+ LockBoxSize = sizeof (SMRAM_CPU_DATA) +
+ SmramCpuDataTemplate.GdtrProfileSize +
+ SmramCpuDataTemplate.GdtSize +
+ SmramCpuDataTemplate.IdtrProfileSize +
+ SmramCpuDataTemplate.IdtSize +
+ SmramCpuDataTemplate.CpuPrivateDataSize +
+ SmramCpuDataTemplate.S3BootScriptTableSize +
+ SmramCpuDataTemplate.S3BspMtrrTableSize +
+ SmramCpuDataTemplate.MicrocodePointerBufferSize +
+ SmramCpuDataTemplate.MicrocodeDataBufferSize;
+
+ DEBUG ((EFI_D_INFO, "LockBoxSize - %x\n", LockBoxSize));
+ DEBUG ((EFI_D_INFO, "SmramCpuData.GdtrProfileSize - %x\n", SmramCpuDataTemplate.GdtrProfileSize));
+ DEBUG ((EFI_D_INFO, "SmramCpuData.GdtSize - %x\n", SmramCpuDataTemplate.GdtSize));
+ DEBUG ((EFI_D_INFO, "SmramCpuData.IdtrProfileSize - %x\n", SmramCpuDataTemplate.IdtrProfileSize));
+ DEBUG ((EFI_D_INFO, "SmramCpuData.IdtSize - %x\n", SmramCpuDataTemplate.IdtSize));
+ DEBUG ((EFI_D_INFO, "SmramCpuData.CpuPrivateDataSize - %x\n", SmramCpuDataTemplate.CpuPrivateDataSize));
+ DEBUG ((EFI_D_INFO, "SmramCpuData.S3BootScriptTableSize - %x\n", SmramCpuDataTemplate.S3BootScriptTableSize));
+ DEBUG ((EFI_D_INFO, "SmramCpuData.S3BspMtrrTableSize - %x\n", SmramCpuDataTemplate.S3BspMtrrTableSize));
+ DEBUG ((EFI_D_INFO, "SmramCpuData.MicrocodePointerBufferSize - %x\n", SmramCpuDataTemplate.MicrocodePointerBufferSize));
+ DEBUG ((EFI_D_INFO, "SmramCpuData.MicrocodeDataBufferSize - %x\n", SmramCpuDataTemplate.MicrocodeDataBufferSize));
+ DEBUG ((EFI_D_INFO, "SmramCpuData.GdtrProfileOffset - %x\n", SmramCpuDataTemplate.GdtrProfileOffset));
+ DEBUG ((EFI_D_INFO, "SmramCpuData.GdtOffset - %x\n", SmramCpuDataTemplate.GdtOffset));
+ DEBUG ((EFI_D_INFO, "SmramCpuData.IdtrProfileOffset - %x\n", SmramCpuDataTemplate.IdtrProfileOffset));
+ DEBUG ((EFI_D_INFO, "SmramCpuData.IdtOffset - %x\n", SmramCpuDataTemplate.IdtOffset));
+ DEBUG ((EFI_D_INFO, "SmramCpuData.CpuPrivateDataOffset - %x\n", SmramCpuDataTemplate.CpuPrivateDataOffset));
+ DEBUG ((EFI_D_INFO, "SmramCpuData.S3BootScriptTableOffset - %x\n", SmramCpuDataTemplate.S3BootScriptTableOffset));
+ DEBUG ((EFI_D_INFO, "SmramCpuData.S3BspMtrrTableOffset - %x\n", SmramCpuDataTemplate.S3BspMtrrTableOffset));
+ DEBUG ((EFI_D_INFO, "SmramCpuData.MicrocodePointerBufferOffset - %x\n", SmramCpuDataTemplate.MicrocodePointerBufferOffset));
+ DEBUG ((EFI_D_INFO, "SmramCpuData.MicrocodeDataBufferOffset - %x\n", SmramCpuDataTemplate.MicrocodeDataBufferOffset));
+
+ ///
+ /// Allocate Normal Memory
+ ///
+ Status = (gBS->AllocatePool)(EfiBootServicesData, LockBoxSize, &SmramCpuData);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Allocate SMRAM
+ ///
+ Status = SmmBase->SmmAllocatePool (
+ SmmBase,
+ EfiRuntimeServicesData,
+ LockBoxSize + EFI_PAGE_SIZE,
+ &LockBoxData
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Let it page aligned
+ ///
+ LockBoxData = (UINT8 *) (((UINTN) LockBoxData + EFI_PAGE_SIZE - 1) &~(EFI_PAGE_SIZE - 1));
+ DEBUG ((EFI_D_INFO, "CPU SMRAM NVS Data - %x\n", LockBoxData));
+
+ ///
+ /// Copy data buffer
+ ///
+ CopyMem (SmramCpuData, &SmramCpuDataTemplate, sizeof (SmramCpuDataTemplate));
+
+ CopyMem (
+ SmramCpuData + SmramCpuDataTemplate.GdtrProfileOffset,
+ (VOID *) (UINTN) mAcpiCpuData->GdtrProfile,
+ SmramCpuDataTemplate.GdtrProfileSize
+ );
+ CopyMem (
+ SmramCpuData + SmramCpuDataTemplate.GdtOffset,
+ (VOID *) (UINTN) Gdtr->Base,
+ SmramCpuDataTemplate.GdtSize
+ );
+ CopyMem (
+ SmramCpuData + SmramCpuDataTemplate.IdtrProfileOffset,
+ (VOID *) (UINTN) mAcpiCpuData->IdtrProfile,
+ SmramCpuDataTemplate.IdtrProfileSize
+ );
+ CopyMem (
+ SmramCpuData + SmramCpuDataTemplate.IdtOffset,
+ (VOID *) (UINTN) Idtr->Base,
+ SmramCpuDataTemplate.IdtSize
+ );
+ CopyMem (
+ SmramCpuData + SmramCpuDataTemplate.CpuPrivateDataOffset,
+ (VOID *) (UINTN) mAcpiCpuData->CpuPrivateData,
+ SmramCpuDataTemplate.CpuPrivateDataSize
+ );
+ CopyMem (
+ SmramCpuData + SmramCpuDataTemplate.S3BootScriptTableOffset,
+ (VOID *) (UINTN) mMPSystemData->S3DataPointer.S3BootScriptTable,
+ SmramCpuDataTemplate.S3BootScriptTableSize
+ );
+ CopyMem (
+ SmramCpuData + SmramCpuDataTemplate.S3BspMtrrTableOffset,
+ (VOID *) (UINTN) mMPSystemData->S3DataPointer.S3BspMtrrTable,
+ SmramCpuDataTemplate.S3BspMtrrTableSize
+ );
+ Microcode = (VOID *) (UINTN) mAcpiCpuData->MicrocodePointerBuffer;
+ if (Microcode != NULL) {
+ ///
+ /// Copy Microcode Pointer Buffer
+ ///
+ CopyMem (
+ SmramCpuData + SmramCpuDataTemplate.MicrocodePointerBufferOffset,
+ Microcode,
+ SmramCpuDataTemplate.MicrocodePointerBufferSize
+ );
+ ///
+ /// Copy Microcode Data
+ ///
+ Index = 0;
+ MicrocodeSize = 0;
+ LockBoxMicrocode = SmramCpuData + SmramCpuDataTemplate.MicrocodeDataBufferOffset;
+ while (Microcode[Index] != NULL) {
+ if (Microcode[Index]->DataSize == 0) {
+ MicrocodeSize = 2048;
+ } else {
+ MicrocodeSize = Microcode[Index]->TotalSize;
+ }
+
+ CopyMem (LockBoxMicrocode, Microcode[Index], MicrocodeSize);
+ LockBoxMicrocode += MicrocodeSize;
+ Index++;
+ }
+ }
+
+ ///
+ /// Copy to SMRAM
+ ///
+ ///
+ /// We have to use SMI to copy SMRAM, because we can not access SMRAM after SMRR enabled.
+ /// SMM_ACCESS.Open () takes no effect.
+ ///
+ VarSize = sizeof (SmramCpuDataAddr);
+ SmramCpuDataAddr.LockBoxData = (UINT64) (UINTN) LockBoxData;
+ SmramCpuDataAddr.SmramCpuData = (UINT64) (UINTN) SmramCpuData;
+ SmramCpuDataAddr.LockBoxSize = (UINT64) LockBoxSize;
+
+ Status = gRT->SetVariable (
+ SMRAM_CPU_DATA_VARIABLE,
+ &gSmramCpuDataVariableGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ VarSize,
+ &SmramCpuDataAddr
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Fill SMI data port
+ ///
+ Status = SmmControl->GetRegisterInfo (SmmControl, &SmiRegister);
+ ASSERT_EFI_ERROR (Status);
+ IoWrite8 (SmiRegister.SmiDataRegister, SMM_FROM_CPU_DRIVER_SAVE_INFO);
+
+ ///
+ /// Trigger SMI
+ ///
+ ArgBufferSize = sizeof (ArgBuffer);
+ ArgBuffer = mSmmbaseSwSmiNumber;
+ Status = SmmControl->Trigger (SmmControl, (INT8 *) &ArgBuffer, &ArgBufferSize, FALSE, 0);
+ Status = SmmControl->Clear (SmmControl, 0);
+ return;
+}
+
+/**
+ This function is invoked when LegacyBios protocol is installed, we must
+ allocate reserved memory under 1M for AP.
+
+ @param[in] Event - The triggered event.
+ @param[in] Context - Context for this event.
+**/
+VOID
+EFIAPI
+ReAllocateEbdaMemoryForAP (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ EFI_PHYSICAL_ADDRESS EbdaOld;
+ EFI_PHYSICAL_ADDRESS EbdaNew;
+ UINTN EbdaSize;
+ EFI_STATUS Status;
+
+ ///
+ /// Check whether this is real LegacyBios notification
+ ///
+ Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+ ///
+ /// PLEASE NOTE:
+ /// For legacy implementation, we have reserved 0x9F000 to 0x9FFFF for S3 usage in CSM,
+ /// No don't need to allocate it again
+ /// This range will be used for MpS3 driver and S3Resume driver on S3 boot path
+ /// The base needs to be aligned to 4K to satisfy the AP vector requirement
+ /// The original implementation requires 8K from legacy memory form E/F segment,
+ /// which needs lock/unlock and makes lots of code chipset dependent on S3 boot path
+ /// Here we just use normal low memory to eliminate the dependency
+ /// In this case, EBDA will start from 0x9F000 - sizeof (EBDA) in CSM definition
+ /// CSM EBDA base and memory size in BDA area needs to be consistent with this
+ ///
+ ///
+ /// Get EDBA address/length and turn it into the S3 reserved address
+ /// The length of this range is limited so we need to keep the real mode code small
+ ///
+ EbdaOld = (EFI_PHYSICAL_ADDRESS) (*(UINT16 *) (UINTN) 0x40E) << 4;;
+ EbdaSize = (UINTN) (*((UINT8 *) (UINTN) EbdaOld));
+
+//(AMI_CHG+)>
+#if (REQUEST_EBDA_SIZE == 0x1000)
+ mLegacyRegion = EbdaOld + (EbdaSize << 10);
+ mLegacyRegion = (mLegacyRegion - 0x1000) & 0xFFFFF000;
+ EbdaNew = mLegacyRegion - (EbdaSize << 10);
+#else
+ *(UINT8 *) ((UINTN) EbdaOld) = (UINT8)(EbdaSize + 8);
+ mLegacyRegion = EbdaOld + (EbdaSize << 10);
+ mLegacyRegion = (mLegacyRegion - REQUEST_EBDA_SIZE) & 0xFFFFF000;
+ EbdaNew = mLegacyRegion - (EbdaSize << 10);
+ mEbdaOffset = EbdaSize << 10;
+#endif
+//<(AMI_CHG+)
+
+ (*(UINT16 *) (UINTN) 0x40E) = (UINT16) (EbdaNew >> 4);
+ CopyMem ((VOID *) (UINTN) EbdaNew, (VOID *) (UINTN) EbdaOld, EbdaSize << 10);
+
+ ///
+ /// Update 40:13 with the new size of available base memory
+ ///
+ *(UINT16 *) (UINTN) 0x413 = (*(UINT16 *) (UINTN) 0x413) - (UINT16) (((EbdaOld - EbdaNew) >> 10));
+
+ ///
+ /// Free the Wake-up buffer and re-declare it as Reserved Memory
+ ///
+ DEBUG ((EFI_D_INFO, "Legacy region freed before re-allocation: %X\n", mLegacyRegion));
+ Status = (gBS->FreePages) (mLegacyRegion, 1);
+ ASSERT_EFI_ERROR (Status);
+ DEBUG ((EFI_D_INFO, "Allocate and reserve the 4K buffer for Legacy Region\n"));
+ Status = (gBS->AllocatePages)(AllocateAddress, EfiReservedMemoryType, 1, &mLegacyRegion);
+ ASSERT_EFI_ERROR (Status);
+ DEBUG ((EFI_D_INFO, "mLegacyRegion CSM - %x\n", mLegacyRegion));
+}
+
+/**
+ This function is invoked when LegacyBios protocol is installed, we must
+ allocate reserved memory under 1M for AP.
+
+ @param[in] Event - The triggered event.
+ @param[in] Context - Context for this event.
+**/
+VOID
+EFIAPI
+ReAllocateMemoryForAP (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS LegacyRegion;
+ MP_CPU_EXCHANGE_INFO *ExchangeInfo;
+ MONITOR_MWAIT_DATA *MonitorAddr;
+ UINTN Index;
+ UINT64 MaxCstate;
+ UINT64 CStateLimit;
+ UINT32 SubStates;
+ EFI_CPUID_REGISTER MwaitInfo;
+ BOOLEAN HasCsm;
+ EFI_MP_SERVICES_PROTOCOL *MpService;
+
+ VOID *ExitPmAuth;
+ STATIC BOOLEAN InitDone = FALSE;
+
+ ///
+ /// Check whether this is real ExitPmAuth notification
+ ///
+ Status = gBS->LocateProtocol (&gExitPmAuthProtocolGuid, NULL, &ExitPmAuth);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+ ///
+ /// Make sure it is invoked only once.
+ ///
+ if (InitDone) {
+ return;
+ }
+
+ InitDone = TRUE;
+
+ Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios);
+ if (EFI_ERROR (Status)) {
+ HasCsm = FALSE;
+ } else {
+ HasCsm = TRUE;
+ }
+
+ while (ApRunning ()) {
+ CpuPause ();
+ }
+ ///
+ /// Re-load microcode patch here!!!
+ ///
+ ReLoadMicrocodeBeforeBoot ();
+
+ if (HasCsm) {
+//(AMI_CHG+)>
+#if (REQUEST_EBDA_SIZE == 0x1000)
+ LegacyRegion = mLegacyRegion;
+#else
+ EFI_PHYSICAL_ADDRESS CurEbda;
+
+ CurEbda = (EFI_PHYSICAL_ADDRESS) (*(UINT16 *) (UINTN) 0x40E) << 4;
+ LegacyRegion = (EFI_PHYSICAL_ADDRESS) ((UINTN)CurEbda + mEbdaOffset);
+ LegacyRegion += 0x1000;
+ LegacyRegion &= 0xffff000;
+#endif
+//<(AMI_CHG+)
+ DEBUG ((EFI_D_INFO, "Using LegacyRegion CSM - %x\n", LegacyRegion));
+ } else {
+ ///
+ /// The BackBuffer is 4k. Allocate 0x2000 bytes from below 640K memory to ensure 4k aligned spaces of 0x1000 bytes,
+ /// since Alignment argument does not work.
+ ///
+ LegacyRegion = 0x9FFFF;
+ Status = (gBS->AllocatePages)(AllocateMaxAddress, EfiReservedMemoryType, EFI_SIZE_TO_PAGES (0x2000), &LegacyRegion);
+ ASSERT_EFI_ERROR (Status);
+ DEBUG ((EFI_D_INFO, "LegacyRegion NonCSM - %x\n", LegacyRegion));
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+ }
+ ///
+ /// This address should be less than A seg.
+ /// And it should be aligned to 4K
+ ///
+ ASSERT (!((UINTN) LegacyRegion & 0x0FFF) && ((UINTN) LegacyRegion < 0xA0000));
+
+ mAcpiCpuData->WakeUpBuffer = (EFI_PHYSICAL_ADDRESS) LegacyRegion;
+ mAcpiCpuData->WakeUpBuffer = (mAcpiCpuData->WakeUpBuffer + 0x0fff) & 0x0fffff000;
+
+ ExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (mBackupBuffer + MP_CPU_EXCHANGE_INFO_OFFSET);
+ ExchangeInfo->BufferStart = (UINT32) mAcpiCpuData->WakeUpBuffer;
+ CopyMem (
+ (VOID *) (UINTN) mAcpiCpuData->WakeUpBuffer,
+ (VOID *) (UINTN) mBackupBuffer,
+ EFI_PAGE_SIZE
+ );
+ RedirectFarJump ();
+
+ if (HasCsm) {
+ Status = LegacyBios->CopyLegacyRegion (
+ LegacyBios,
+ sizeof (MP_CPU_EXCHANGE_INFO),
+ (VOID *) (UINTN) (mAcpiCpuData->WakeUpBuffer + MP_CPU_EXCHANGE_INFO_OFFSET),
+ (VOID *) (UINTN) (mBackupBuffer + MP_CPU_EXCHANGE_INFO_OFFSET)
+ );
+ }
+
+ ///
+ /// Set all APs to deepest C-State before ready to boot for better power saving,
+ /// if boot to DOS/EFI_SHARE or any operating system that running only single thread.
+ ///
+ ExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (mAcpiCpuData->WakeUpBuffer + MP_CPU_EXCHANGE_INFO_OFFSET);
+ if (mPlatformCpu->CpuConfig->ApHandoffManner != WakeUpApPerHltLoop) {
+ ///
+ /// Based on HSW BWG 17.2.7, BIOS should use CPUID.(EAX=5) Monitor/Mwait Leaf and also check MSR E2h[3:0] Package C-state limit to determine
+ /// if the processor supports MONITOR/MWAIT extensions for various Haswell specific C-states and sub C-states.
+ ///
+ CStateLimit = AsmReadMsr64 (MSR_PMG_CST_CONFIG) & B_PACKAGE_C_STATE_LIMIT;
+ AsmCpuid (5, &MwaitInfo.RegEax, &MwaitInfo.RegEbx, &MwaitInfo.RegEcx, &MwaitInfo.RegEdx);
+ MaxCstate = 0;
+ SubStates = 0;
+ if (MwaitInfo.RegEcx & BIT0) {
+ switch (CStateLimit) {
+ case V_CSTATE_LIMIT_C10:
+ SubStates = (MwaitInfo.RegEdx & (BIT31 | BIT30 | BIT29 | BIT28)) >> 28;
+ MaxCstate = 0x60 | (SubStates - 1);
+ break;
+
+ case V_CSTATE_LIMIT_C9:
+ SubStates = (MwaitInfo.RegEdx & (BIT27 | BIT26 | BIT25 | BIT24)) >> 24;
+ MaxCstate = 0x50 | (SubStates - 1);
+ break;
+
+ case V_CSTATE_LIMIT_C8:
+ SubStates = (MwaitInfo.RegEdx & (BIT23 | BIT22 | BIT21 | BIT20)) >> 20;
+ MaxCstate = 0x40 | (SubStates - 1);
+ break;
+
+ case V_CSTATE_LIMIT_C7S:
+ SubStates = (MwaitInfo.RegEdx & (BIT19 | BIT18 | BIT17 | BIT16)) >> 16;
+ MaxCstate = 0x30 | (SubStates - 1);
+ break;
+
+ case V_CSTATE_LIMIT_C7:
+ SubStates = (MwaitInfo.RegEdx & (BIT19 | BIT18 | BIT17 | BIT16)) >> 16;
+ MaxCstate = 0x30 | (SubStates - 1);
+ break;
+
+ case V_CSTATE_LIMIT_C6:
+ SubStates = (MwaitInfo.RegEdx & (BIT15 | BIT14 | BIT13 | BIT12)) >> 12;
+ MaxCstate = 0x20 | (SubStates - 1);
+ break;
+
+ case V_CSTATE_LIMIT_C3:
+ SubStates = (MwaitInfo.RegEdx & (BIT11 | BIT10 | BIT9 | BIT8)) >> 8;
+ MaxCstate = 0x10 | (SubStates - 1);
+ break;
+
+ case V_CSTATE_LIMIT_C1:
+ SubStates = (MwaitInfo.RegEdx & (BIT7 | BIT6 | BIT5 | BIT4)) >> 4;
+ MaxCstate = 0x00 | (SubStates - 1);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ ///
+ /// Use WakeUpApPerMwaitLoop32 if CR4 paging table entities are not allocated as RESERVED MEMORY TYPE in 64-bits mode.
+ ///
+ ExchangeInfo->WakeUpApManner = WakeUpApPerMwaitLoop32;
+ for (Index = 0; Index < mMPSystemData->NumberOfCpus; Index++) {
+ MonitorAddr = (MONITOR_MWAIT_DATA *) ((UINT8 *) ExchangeInfo->StackStart + (Index + 1) * ExchangeInfo->StackSize - MONITOR_FILTER_SIZE);
+ MonitorAddr->WakeUpApVectorChangeFlag = TRUE;
+ MonitorAddr->MwaitTargetCstate = MaxCstate;
+ }
+ } else {
+ ExchangeInfo->WakeUpApManner = WakeUpApPerHltLoop;
+ }
+
+ ///
+ /// Locate MpServices protocol
+ ///
+ Status = gBS->LocateProtocol (
+ &gEfiMpServiceProtocolGuid,
+ NULL,
+ (VOID **) &MpService
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Move Limit CPUID Maxval configuration here to not impact the BOOT
+ /// After setting this, no code can execute CPUID function > 3.
+ ///
+ ProgramCpuidLimit (MpService);
+ Status = MpService->StartupAllAPs (
+ MpService,
+ ProgramCpuidLimit,
+ FALSE,
+ NULL,
+ 0,
+ MpService,
+ NULL
+ );
+
+ ///
+ /// Invoke the InitializeSmram directly, since it is in ExitPmAuth event.
+ ///
+ InitializeSmramDataContent (NULL, NULL);
+}
+
+/**
+ This function is invoked by EFI_EVENT_SIGNAL_LEGACY_BOOT.
+ Before booting to legacy OS, reset AP's wakeup buffer address,
+ preparing for S3 usage.
+
+ @param[in] Event - The triggered event.
+ @param[in] Context - Context for this event.
+**/
+VOID
+ResetAPs (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ return;
+}
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/MpCommon.h b/ReferenceCode/Haswell/CpuInit/Dxe/MpCommon.h
new file mode 100644
index 0000000..7677e80
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/MpCommon.h
@@ -0,0 +1,606 @@
+/** @file
+ Some definitions for MP and HT driver.
+
+@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 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
+
+**/
+#ifndef _MP_COMMON_
+#define _MP_COMMON_
+
+#include "ProcessorData.h"
+#include "CacheData.h"
+#include "Exception.h"
+#include "ProcessorDef.h"
+
+//
+// Protocol produced by this driver
+//
+#include EFI_PROTOCOL_PRODUCER (MpService)
+
+//
+// Protocol consumed by this driver
+//
+#include EFI_PROTOCOL_DEFINITION (CpuPlatformPolicy)
+
+//
+// GUID definitions
+//
+#include EFI_GUID_DEFINITION (HtBistHOB)
+#include EFI_GUID_DEFINITION (SmramCpuDataVariable)
+#include EFI_GUID_DEFINITION (SmramCpuDataHeader)
+
+#define VacantFlag 0x00
+#define NotVacantFlag 0xff
+#define MICROSECOND 10
+#define MAXIMUM_CPU_NUMBER 0x40
+#define STACK_SIZE_PER_PROC 0x8000
+
+#define IO_APIC_INDEX_REGISTER 0xFEC00000
+#define IO_APIC_DATA_REGISTER 0xFEC00010
+
+///
+/// Data structure used in MP/HT driver
+///
+#define MP_CPU_EXCHANGE_INFO_OFFSET (0x1000 - 0x400)
+#define MP_CPU_LEGACY_RESET_INFO_OFFSET (0x100 - 0x20)
+
+#define SMM_FROM_CPU_DRIVER_SAVE_INFO 0x81
+
+#pragma pack(1)
+#define SIZE_OF_MCE_HANDLER 16
+
+typedef struct {
+ UINT16 LimitLow;
+ UINT16 BaseLow;
+ UINT8 BaseMiddle;
+ UINT16 Attributes;
+ UINT8 BaseHigh;
+} SEGMENT_DESCRIPTOR;
+
+#pragma pack()
+
+#define BREAK_TO_RUN_AP_SIGNAL 0x6E755200
+#define MONITOR_FILTER_SIZE 0x40
+
+typedef enum {
+ WakeUpApCounterInit = 0,
+ WakeUpApPerHltLoop = 1,
+ WakeUpApPerMwaitLoop = 2,
+ WakeUpApPerRunLoop = 3,
+ WakeUpApPerMwaitLoop32= 4,
+ WakeUpApPerRunLoop32 = 5
+} WAKEUP_AP_MANNER;
+
+typedef struct {
+ UINTN BreakToRunApSignal;
+ UINTN HltLoopBreakCounter;
+ UINTN MwaitLoopBreakCounter;
+ UINTN RunLoopBreakCounter;
+ UINTN MwaitLoopBreakCounter32;
+ UINTN RunLoopBreakCounter32;
+ UINTN WakeUpApVectorChangeFlag;
+ UINTN MwaitTargetCstate;
+} MONITOR_MWAIT_DATA;
+
+typedef struct {
+ UINT32 Number;
+ UINT32 BIST;
+} BIST_INFO;
+
+typedef struct {
+ UINTN Lock;
+ VOID *StackStart;
+ UINTN StackSize;
+ VOID *ApFunction;
+ PSEUDO_DESCRIPTOR GdtrProfile;
+ PSEUDO_DESCRIPTOR IdtrProfile;
+ UINT32 BufferStart;
+ UINT32 Cr3;
+ UINT32 InitFlag;
+ WAKEUP_AP_MANNER WakeUpApManner;
+ BIST_INFO BistBuffer[MAXIMUM_CPU_NUMBER];
+} MP_CPU_EXCHANGE_INFO;
+
+extern ACPI_CPU_DATA *mAcpiCpuData;
+
+//
+// Protocol interface functions
+//
+/**
+ Get general MP information
+
+ @param[in] This - EFI_MP_SERVICE_PROTOCOL
+ @param[in] NumberOfCPUs - Number of processors
+ @param[in] MaxiumNumberOfCPUs - Max supported number of processors
+ @param[in] NumberOfEnabledCPUs - Number of processors enabled
+ @param[in] RendezvousIntNumber - number of Rendezvous procedure
+ @param[in] RendezvousProcLength - length of Rendezvous procedure
+
+ @retval EFI_SUCCESS - always return success
+**/
+EFI_STATUS
+EFIAPI
+GetGeneralMPInfo (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ OUT UINTN *NumberOfCPUs,
+ OUT UINTN *MaxiumNumberOfCPUs,
+ OUT UINTN *NumberOfEnabledCPUs,
+ OUT UINTN *RendezvousIntNumber,
+ OUT UINTN *RendezvousProcLength
+ );
+
+/**
+ Get processor context
+
+ @param[in] This - EFI_MP_SERVICE_PROTOCOL
+ @param[in] ProcessorNumber - Cpu number
+ @param[in] BufferLength - buffer length
+ @param[in] ProcessorContextBuffer - pointer to the buffer that will be updated
+
+ @retval EFI_INVALID_PARAMETER - buffer is NULL or CpuNumber our of range
+ @retval EFI_BUFFER_TOO_SMALL - buffer too small
+ @retval EFI_SUCCESS - got processor context successfully
+**/
+EFI_STATUS
+EFIAPI
+GetProcessorContext (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ IN OUT UINTN *BufferLength,
+ IN OUT EFI_MP_PROC_CONTEXT *ProcessorContextBuffer
+ );
+
+/**
+ MP Service to get specified application processor (AP)
+ to execute a caller-provided code stream.
+
+ @param[in] This - Pointer to MP Service Protocol
+ @param[in] Procedure - The procedure to be assigned to AP.
+ @param[in] ProcessorNumber - Cpu number
+ @param[in] WaitEvent - If timeout, the event to be triggered after this AP finishes.
+ @param[in] TimeoutInMicroSecs - The timeout value in microsecond. Zero means infinity.
+ @param[in] ProcArguments - Argument for Procedure.
+
+ @retval EFI_INVALID_PARAMETER - Procudure is NULL.
+ @retval EFI_INVALID_PARAMETER - Number of CPU out of range, or it belongs to BSP.
+ @retval EFI_INVALID_PARAMETER - Specified CPU is not idle.
+ @retval EFI_SUCCESS - The AP has finished.
+ @retval EFI_TIMEOUT - Time goes out before the AP has finished.
+**/
+EFI_STATUS
+EFIAPI
+StartupThisAP (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN UINTN ProcessorNumber,
+ IN EFI_EVENT WaitEvent OPTIONAL,
+ IN UINTN TimeoutInMicroSecs OPTIONAL,
+ IN OUT VOID *ProcArguments OPTIONAL
+ );
+
+/**
+ MP Service to get all the available application processors (APs)
+ to execute a caller-provided code stream.
+
+ @param[in] This - Pointer to MP Service Protocol
+ @param[in] Procedure - The procedure to be assigned to APs.
+ @param[in] SingleThread - If true, all APs execute in block mode.
+ Otherwise, all APs exceute in non-block mode.
+ @param[in] WaitEvent - If timeout, the event to be triggered after all APs finish.
+ @param[in] TimeoutInMicroSecs - The timeout value in microsecond. Zero means infinity.
+ @param[in] ProcArguments - Argument for Procedure.
+ @param[in] FailedCPUList - If not NULL, all APs that fail to start will be recorded in the list.
+
+ @retval EFI_INVALID_PARAMETER - Procudure is NULL.
+ @retval EFI_SUCCESS - Only 1 logical processor exists.
+ @retval EFI_SUCCESS - All APs have finished.
+ @retval EFI_TIMEOUT - Time goes out before all APs have finished.
+**/
+EFI_STATUS
+EFIAPI
+StartupAllAPs (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN BOOLEAN SingleThread,
+ IN EFI_EVENT WaitEvent OPTIONAL,
+ IN UINTN TimeoutInMicroSecs OPTIONAL,
+ IN OUT VOID *ProcArguments OPTIONAL,
+ OUT UINTN *FailedCPUList OPTIONAL
+ );
+
+/**
+ MP Service to makes the current BSP into an AP and then switches the
+ designated AP into the AP. This procedure is usually called after a CPU
+ test that has found that BSP is not healthy to continue it's responsbilities.
+
+ @param[in] This - Pointer to MP Service Protocol.
+ @param[in] ProcessorNumber - The handle number of processor.
+ @param[in] OldBSPState - Whether to enable or disable the original BSP.
+
+ @retval EFI_INVALID_PARAMETER - Number for Specified AP out of range.
+ @retval EFI_INVALID_PARAMETER - Number of specified CPU belongs to BSP.
+ @retval EFI_NOT_READY - Specified AP is not idle.
+ @retval EFI_SUCCESS - BSP successfully switched.
+**/
+EFI_STATUS
+EFIAPI
+SwitchBSP (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ IN BOOLEAN OldBSPState
+ );
+
+/**
+ This procedure sends an IPI to the designated processor in
+ the requested delivery mode with the requested vector.
+
+ @param[in] This - Pointer to MP Service Protocol.
+ @param[in] ProcessorNumber - The handle number of processor.
+ @param[in] VectorNumber - Vector number.
+ @param[in] DeliveryMode - I/O APIC Interrupt Deliver Modes
+
+ @retval EFI_INVALID_PARAMETER - Input paramters were not correct.
+ @retval Other status - Status returned by SendInterrupt ()
+**/
+EFI_STATUS
+EFIAPI
+SendIPI (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ IN UINTN VectorNumber,
+ IN UINTN DeliveryMode
+ );
+
+/**
+ This procedure enables or disables APs.
+
+ @param[in] This - Pointer to MP Service Protocol.
+ @param[in] ProcessorNumber - The handle number of processor.
+ @param[in] NewAPState - Indicate new desired AP state
+ @param[in] HealthState - If not NULL, it points to the value that specifies the new health status of the AP.
+ If it is NULL, this parameter is ignored.
+
+ @retval EFI_INVALID_PARAMETER - Input paramters were not correct.
+ @retval EFI_SUCCESS - Function completed successfully
+**/
+EFI_STATUS
+EFIAPI
+EnableDisableAP (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ IN BOOLEAN NewAPState,
+ IN EFI_MP_HEALTH *HealthState OPTIONAL
+ );
+
+/**
+ Implementation of WhoAmI() service of MP Services Protocol.
+
+ This service lets the caller processor get its handle number.
+ This service may be called from the BSP and APs.
+
+ @param[in] This - A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] ProcessorNumber - Pointer to the handle number of AP.
+
+ @retval EFI_SUCCESS - Processor number successfully returned.
+ @retval EFI_INVALID_PARAMETER - ProcessorNumber is NULL
+**/
+EFI_STATUS
+EFIAPI
+WhoAmI (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ OUT UINTN *ProcessorNumber
+ );
+
+///
+/// Functions shared in MP/HT drivers
+///
+/**
+ Send interrupt to CPU
+
+ @param[in] BroadcastMode - interrupt broadcast mode
+ @param[in] ApicID - APIC ID for sending interrupt
+ @param[in] VectorNumber - Vector number
+ @param[in] DeliveryMode - Interrupt delivery mode
+ @param[in] TriggerMode - Interrupt trigger mode
+ @param[in] Assert - Interrupt pin polarity
+
+ @retval EFI_INVALID_PARAMETER - input parameter not correct
+ @retval EFI_NOT_READY - there was a pending interrupt
+ @retval EFI_SUCCESS - interrupt sent successfully
+**/
+EFI_STATUS
+SendInterrupt (
+ IN UINT32 BroadcastMode,
+ IN UINT32 ApicID,
+ IN UINT32 VectorNumber,
+ IN UINT32 DeliveryMode,
+ IN UINT32 TriggerMode,
+ IN BOOLEAN Assert
+ );
+
+/**
+ Get APIC ID of processor
+
+ @param[in] ApicBase - APIC base
+ @param[in] ApicVersionNumber - APIC version
+
+ @retval APIC ID of processor
+**/
+UINT32
+GetApicID (
+ OUT EFI_PHYSICAL_ADDRESS *ApicBase OPTIONAL,
+ OUT UINT32 *ApicVersionNumber OPTIONAL
+ );
+
+/**
+ Programs XAPIC registers.
+
+ @param[in] BSP - Is this BSP
+**/
+VOID
+ProgramXApic (
+ IN BOOLEAN BSP
+ );
+
+/**
+ Allocate a temporary memory under 1MB for MP Init to perform INIT-SIPI.
+ This buffer also provides memory for stack/data for MP running.
+
+ @param[in] WakeUpBuffer - Return buffer location
+
+ @retval EFI_SUCCESS if ok to get a memory under 1MB for MP running.
+**/
+EFI_STATUS
+AllocateWakeUpBuffer (
+ OUT EFI_PHYSICAL_ADDRESS *WakeUpBuffer
+ );
+
+///
+/// Assembly functions implemented in MP/HT drivers
+///
+/**
+ Lock APs
+
+ @param[in] Lock - Lock state
+**/
+VOID
+AsmAcquireMPLock (
+ IN UINT8 *Lock
+ );
+
+/**
+ Release APs
+
+ @param[in] Lock - Lock state
+**/
+VOID
+AsmReleaseMPLock (
+ IN UINT8 *Lock
+ );
+
+/**
+ Get GDTR and IDTR
+
+ @param[in] Gdt - will be stored GDTR
+ @param[in] Idt - will be stored IDTR
+**/
+VOID
+AsmGetGdtrIdtr (
+ OUT PSEUDO_DESCRIPTOR **Gdt,
+ OUT PSEUDO_DESCRIPTOR **Idt
+ );
+
+/**
+ Prepare GDTR and IDTR for AP
+
+ @param[in] GDTR - The GDTR profile
+ @param[in] IDTR - The IDTR profile
+
+ @retval EFI_STATUS - status returned by each sub-routine
+ @retval EFI_SUCCESS - GDTR and IDTR has been prepared for AP
+**/
+EFI_STATUS
+PrepareGdtIdtForAP (
+ OUT PSEUDO_DESCRIPTOR *GDTR,
+ OUT PSEUDO_DESCRIPTOR *IDTR
+ );
+
+/**
+ Allocate Reserved Memory
+
+ @param[in] Size - Memory Size
+ @param[in] Alignment - Alignment size
+ @param[in] Pointer - return memory location
+
+ @retval EFI_SUCCESS - Allocate a reserved memory successfully
+**/
+EFI_STATUS
+AllocateAlignedReservedMemory (
+ IN UINTN Size,
+ IN UINTN Alignment,
+ OUT VOID **Pointer
+ );
+
+/**
+ Fill in CPU relevant information into data hub
+
+ @param[in] CpuNumber - CPU number
+ @param[in] CpuDataForDatahub - pointer to data hub that will be updated
+
+ @retval EFI_SUCCESS - always return success
+**/
+EFI_STATUS
+FillinDataforDataHub (
+ IN UINTN CpuNumber,
+ OUT CPU_DATA_FOR_DATAHUB *CpuDataForDatahub
+ );
+
+/**
+ This function is invoked when LegacyBios protocol is installed, we must
+ allocate reserved memory under 1M for AP.
+
+ @param[in] Event - The triggered event.
+ @param[in] Context - Context for this event.
+**/
+VOID
+EFIAPI
+ReAllocateEbdaMemoryForAP (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ This function is invoked when LegacyBios protocol is installed, we must
+ allocate reserved memory under 1M for AP.
+
+ @param[in] Event - The triggered event.
+ @param[in] Context - Context for this event.
+**/
+VOID
+EFIAPI
+ReAllocateMemoryForAP (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ This function is invoked by EFI_EVENT_SIGNAL_LEGACY_BOOT.
+ Before booting to legacy OS, reset it with memory allocated
+ by ReAllocateMemoryForAp() and set local APIC correctly.
+
+ @param[in] Event - The triggered event.
+ @param[in] Context - Context for this event.
+**/
+VOID
+ResetAPs (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ Prepare Wakeup Buffer and stack for APs.
+
+ @param[in] WakeUpBuffer - Pointer to the address of wakeup buffer for output.
+ @param[in] StackAddressStart - Pointer to the stack address of APs for output.
+ @param[in] MaximumCPUsForThisSystem - Maximum CPUs in this system.
+
+ @retval EFI_SUCCESS - Memory successfully prepared for APs.
+ @retval Other - Error occurred while allocating memory.
+**/
+EFI_STATUS
+PrepareMemoryForAPs (
+ OUT EFI_PHYSICAL_ADDRESS *WakeUpBuffer,
+ OUT VOID **StackAddressStart,
+ IN UINTN MaximumCPUsForThisSystem
+ );
+
+/**
+ Prepare exchange information for APs.
+
+ @param[in] ExchangeInfo - Pointer to the exchange info buffer for output.
+ @param[in] StackAddressStart - Start address of APs' stacks.
+ @param[in] ApFunction - Address of function assigned to AP.
+ @param[in] WakeUpBuffer - Pointer to the address of wakeup buffer.
+
+ @retval EFI_SUCCESS - Exchange Info successfully prepared for APs.
+ @retval Other - Error occurred while allocating memory.
+**/
+EFI_STATUS
+PrepareExchangeInfo (
+ OUT MP_CPU_EXCHANGE_INFO *ExchangeInfo,
+ IN VOID *StackAddressStart,
+ IN VOID *ApFunction,
+ IN EFI_PHYSICAL_ADDRESS WakeUpBuffer
+ );
+
+/**
+ Prepare Wakeup Buffer and stack for APs during S3.
+
+ @param[in] WakeUpBuffer - Pointer to the address of wakeup buffer for output.
+ @param[in] StackAddressStart - Pointer to the stack address of APs for output.
+
+ @retval EFI_SUCCESS - Memory successfully prepared for APs.
+**/
+EFI_STATUS
+S3PrepareMemoryForAPs (
+ OUT EFI_PHYSICAL_ADDRESS *WakeUpBuffer,
+ OUT VOID **StackAddressStart
+ );
+
+/**
+ Prepare exchange information for APs during S3.
+
+ @param[in] ExchangeInfo - Pointer to the exchange info for output.
+ @param[in] StackAddressStart - Start address of APs' stacks.
+ @param[in] ApFunction - Address of function assigned to AP.
+ @param[in] WakeUpBuffer - Pointer to the address of wakeup buffer.
+
+ @retval EFI_SUCCESS - Exchange Info successfully prepared for APs.
+**/
+EFI_STATUS
+S3PrepareExchangeInfo (
+ OUT MP_CPU_EXCHANGE_INFO *ExchangeInfo,
+ IN VOID *StackAddressStart,
+ IN VOID *ApFunction,
+ IN EFI_PHYSICAL_ADDRESS WakeUpBuffer
+ );
+
+/**
+ Check whether any AP is running for assigned task.
+
+ @retval TRUE - Some APs are running.
+ @retval FALSE - No AP is running.
+**/
+BOOLEAN
+ApRunning (
+ VOID
+ );
+
+/**
+ Wrapper function for all procedures assigned to AP via MP service protocol.
+ It controls states of AP and invokes assigned precedure.
+**/
+VOID
+ApProcWrapper (
+ VOID
+ );
+
+/**
+ Allocate EfiReservedMemoryType below 4G memory address.
+
+ @param[in] Size - Size of memory to allocate.
+ @param[in] Buffer - Allocated address for output.
+
+ @retval EFI_SUCCESS - Memory successfully allocated.
+ @retval Other - Other errors occur.
+**/
+EFI_STATUS
+AllocateReservedMemoryBelow4G (
+ IN UINTN Size,
+ OUT VOID **Buffer
+ );
+
+/**
+ Dynamically write the far jump destination in APs' wakeup buffer,
+ in order to refresh APs' CS registers for mode switching.
+**/
+VOID
+RedirectFarJump (
+ VOID
+ );
+
+#endif
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/MpService.c b/ReferenceCode/Haswell/CpuInit/Dxe/MpService.c
new file mode 100644
index 0000000..7979618
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/MpService.c
@@ -0,0 +1,2194 @@
+/** @file
+ Code which support multi-processor
+
+@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 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
+
+**/
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "MpService.h"
+#include "PiMpService.h"
+#include "CpuInitDxe.h"
+#include "MachineCheck.h"
+#include "Features.h"
+#include "BootGuardLibrary.h"
+#endif
+
+#include EFI_PROTOCOL_DEFINITION (GenericMemoryTest)
+#include EFI_GUID_DEFINITION (GlobalVariable)
+#include EFI_PROTOCOL_DEFINITION (ExitPmAuth)
+
+extern DXE_CPU_PLATFORM_POLICY_PROTOCOL *mPlatformCpu;
+extern EFI_METRONOME_ARCH_PROTOCOL *mMetronome;
+extern MP_SYSTEM_DATA *mMPSystemData;
+extern UINTN mCommonFeatures;
+extern volatile UINTN mSwitchToLegacyRegionCount;
+extern EFI_CPU_MICROCODE_HEADER **mMicrocodePointerBuffer;
+extern EFI_DATA_HUB_PROTOCOL *mDataHub;
+
+static EFI_HANDLE mHandle = NULL;
+static UINT32 mFinishedCount = 0;
+extern UINT32 mMcuLoadCount;
+STATIC UINT64 mCpuPerfCtrlValue;
+EFI_MP_SERVICES_PROTOCOL mMpService = {
+ GetGeneralMPInfo,
+ GetProcessorContext,
+ StartupAllAPs,
+ StartupThisAP,
+ SwitchBSP,
+ SendIPI,
+ EnableDisableAP,
+ WhoAmI
+};
+
+EFI_PHYSICAL_ADDRESS mOriginalBuffer;
+EFI_PHYSICAL_ADDRESS mBackupBuffer;
+DXE_CPU_INFO_PROTOCOL mCpuInfo;
+
+/**
+ Initialize MP services by MP Service Protocol
+**/
+VOID
+EFIAPI
+InitializeMpServices (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT LegacyBootEvent;
+ EFI_EVENT ExitBootServicesEvent;
+ VOID *Registration;
+
+ LegacyBootEvent = NULL;
+ ExitBootServicesEvent = NULL;
+
+ ///
+ /// Save Mtrr Registers in global data areas
+ ///
+ ReadMtrrRegisters ();
+
+ ///
+ /// Initialize and collect MP related data
+ ///
+ Status = InitializeMpSystemData ();
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ ///
+ /// Register protocol notifacation function for ExitPmAuth protocol
+ ///
+ EfiCreateProtocolNotifyEvent (
+ &gExitPmAuthProtocolGuid,
+ TPL_NOTIFY,
+ ReAllocateMemoryForAP,
+ NULL,
+ &Registration
+ );
+
+ ///
+ /// Register protocol notifaction function to allocate memory in EBDA as early as possible
+ ///
+ EfiCreateProtocolNotifyEvent (
+ &gEfiLegacyBiosProtocolGuid,
+ TPL_NOTIFY,
+ ReAllocateEbdaMemoryForAP,
+ NULL,
+ &Registration
+ );
+
+ ///
+ /// Create legacy boot and EFI boot events to reset APs before OS handoff
+ ///
+ Status = EfiCreateEventLegacyBootEx (
+ EFI_TPL_CALLBACK,
+ ResetAPs,
+ mMPSystemData,
+ &LegacyBootEvent
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = gBS->CreateEvent (
+ EVENT_SIGNAL_EXIT_BOOT_SERVICES,
+ TPL_CALLBACK,
+ ResetAPs,
+ mMPSystemData,
+ &ExitBootServicesEvent
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ ///
+ /// Create timer event to check AP state for non-blocking execution.
+ ///
+ Status = gBS->CreateEvent (
+ EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,
+ EFI_TPL_CALLBACK,
+ CheckAPsStatus,
+ NULL,
+ &mMPSystemData->CheckAPsEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Now install the Frameowrk & PI MP services protocol.
+ ///
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mHandle,
+ &gEfiMpServiceProtocolGuid,
+ &mMpService,
+ &gEfiPiMpServiceProtocolGuid,
+ &mPiMpService,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->SetTimer (
+ mMPSystemData->CheckAPsEvent,
+ TimerPeriodic,
+ 10000 * MICROSECOND
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (EFI_ERROR (Status)) {
+
+Done:
+ if (LegacyBootEvent != NULL) {
+ gBS->CloseEvent (LegacyBootEvent);
+ }
+
+ if (ExitBootServicesEvent != NULL) {
+ gBS->CloseEvent (ExitBootServicesEvent);
+ }
+
+ FreePool (mMPSystemData);
+ }
+}
+
+/**
+ Get general MP information
+
+ @param[in] This - EFI_MP_SERVICE_PROTOCOL
+ @param[in] NumberOfCPUs - Number of processors
+ @param[in] MaximumNumberOfCPUs - Max supported number of processors
+ @param[in] NumberOfEnabledCPUs - Number of processors enabled
+ @param[in] RendezvousIntNumber - number of Rendezvous procedure
+ @param[in] RendezvousProcLength - length of Rendezvous procedure
+
+ @retval EFI_SUCCESS - always return success
+**/
+EFI_STATUS
+EFIAPI
+GetGeneralMPInfo (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ OUT UINTN *NumberOfCPUs,
+ OUT UINTN *MaximumNumberOfCPUs,
+ OUT UINTN *NumberOfEnabledCPUs,
+ OUT UINTN *RendezvousIntNumber,
+ OUT UINTN *RendezvousProcLength
+ )
+{
+ UINTN Index;
+ CPU_DATA_BLOCK *CpuData;
+
+ if (NumberOfCPUs) {
+ *NumberOfCPUs = mMPSystemData->NumberOfCpus;
+ }
+
+ if (MaximumNumberOfCPUs) {
+ *MaximumNumberOfCPUs = mMPSystemData->MaximumCpusForThisSystem;
+ }
+
+ if (RendezvousProcLength) {
+ *RendezvousProcLength = RENDEZVOUS_PROC_LENGTH;
+ }
+
+ if (RendezvousIntNumber) {
+ *RendezvousIntNumber = 0;
+ }
+
+ if (NumberOfEnabledCPUs) {
+ *NumberOfEnabledCPUs = 0;
+ for (Index = 0; Index < mMPSystemData->NumberOfCpus; Index++) {
+ CpuData = &mMPSystemData->CpuData[Index];
+ if (mMPSystemData->EnableSecondaryCpu) {
+ if (CpuData->State != CPU_STATE_DISABLED) {
+ (*NumberOfEnabledCPUs)++;
+ }
+ } else {
+ if (CpuData->State != CPU_STATE_DISABLED && !mMPSystemData->CpuData[Index].SecondaryCpu) {
+ (*NumberOfEnabledCPUs)++;
+ }
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get processor context
+
+ @param[in] This - EFI_MP_SERVICE_PROTOCOL
+ @param[in] CpuNumber - Cpu number
+ @param[in] BufferLength - buffer length
+ @param[in] ProcessorContextBuffer - pointer to the buffer that will be updated
+
+ @retval EFI_INVALID_PARAMETER - buffer is NULL or CpuNumber our of range
+ @retval EFI_BUFFER_TOO_SMALL - buffer too small
+ @retval EFI_SUCCESS - got processor context successfully
+**/
+EFI_STATUS
+EFIAPI
+GetProcessorContext (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN CpuNumber,
+ IN OUT UINTN *BufferLength,
+ IN OUT EFI_MP_PROC_CONTEXT *ProcessorContextBuffer
+ )
+{
+ EFI_MP_PROC_CONTEXT *ProcessorBuffer;
+ CPU_DATA_BLOCK *CpuData;
+
+ if (BufferLength == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*BufferLength < sizeof (EFI_MP_PROC_CONTEXT)) {
+ *BufferLength = sizeof (EFI_MP_PROC_CONTEXT);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ if ((mMPSystemData->NumberOfCpus <= CpuNumber) || (ProcessorContextBuffer == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CpuData = &mMPSystemData->CpuData[CpuNumber];
+
+ *BufferLength = sizeof (EFI_MP_PROC_CONTEXT);
+ ProcessorBuffer = ProcessorContextBuffer;
+
+ ProcessorBuffer->ApicID = CpuData->ApicID;
+
+ ProcessorBuffer->Enabled = TRUE;
+ if (!mMPSystemData->EnableSecondaryCpu) {
+ if (CpuData->SecondaryCpu) {
+ ProcessorBuffer->Enabled = FALSE;
+ }
+ }
+
+ if (CpuData->State == CPU_STATE_DISABLED) {
+ ProcessorBuffer->Enabled = FALSE;
+ }
+
+ if (CpuNumber == mMPSystemData->BSP) {
+ ProcessorBuffer->Designation = EfiCpuBSP;
+ } else {
+ ProcessorBuffer->Designation = EfiCpuAP;
+ }
+
+ ProcessorBuffer->Health.Flags = CpuData->Health;
+ ProcessorBuffer->Health.TestStatus = 0;
+
+ ProcessorBuffer->PackageNumber = CpuData->CpuDataforDatahub.Location.Package;
+ ProcessorBuffer->NumberOfCores = CpuData->CpuDataforDatahub.Location.Core;
+ ProcessorBuffer->NumberOfThreads = CpuData->CpuDataforDatahub.Location.Thread;
+ ProcessorBuffer->ProcessorTestMask = 0;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ MP Service to get specified application processor (AP)
+ to execute a caller-provided code stream.
+
+ @param[in] This - Pointer to MP Service Protocol
+ @param[in] Procedure - The procedure to be assigned to AP.
+ @param[in] CpuNumber - Number of the specified processor.
+ @param[in] WaitEvent - If timeout, the event to be triggered after this AP finishes.
+ @param[in] TimeoutInMicroSecs - The timeout value in microsecond. Zero means infinity.
+ @param[in] ProcArguments - Argument for Procedure.
+
+ @retval EFI_INVALID_PARAMETER - Procudure is NULL.
+ @retval EFI_INVALID_PARAMETER - Number of CPU out of range, or it belongs to BSP.
+ @retval EFI_INVALID_PARAMETER - Specified CPU is not idle.
+ @retval EFI_SUCCESS - The AP has finished.
+ @retval EFI_TIMEOUT - Time goes out before the AP has finished.
+**/
+EFI_STATUS
+EFIAPI
+StartupThisAP (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN UINTN CpuNumber,
+ IN EFI_EVENT WaitEvent OPTIONAL,
+ IN UINTN TimeoutInMicroSecs OPTIONAL,
+ IN OUT VOID *ProcArguments OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ CPU_DATA_BLOCK *CpuData;
+ UINT64 ExpectedTime;
+
+ ///
+ /// Check for invalid CPU number
+ ///
+ if ((CpuNumber >= mMPSystemData->NumberOfCpus) || CpuNumber == mMPSystemData->BSP) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Procedure == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CpuData = &mMPSystemData->CpuData[CpuNumber];
+
+ ///
+ /// As a first step, check if processor is OK to start up code stream.
+ ///
+ if (CpuData->State != CPU_STATE_IDLE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ExpectedTime = CalculateTimeout (TimeoutInMicroSecs);
+
+ mMPSystemData->StartCount = 1;
+ mMPSystemData->FinishCount = 0;
+
+ WakeUpAp (
+ CpuData,
+ Procedure,
+ ProcArguments
+ );
+
+ while (TRUE) {
+ AsmAcquireMPLock (&CpuData->StateLock);
+ if (CpuData->State == CPU_STATE_FINISHED) {
+ CpuData->State = CPU_STATE_IDLE;
+ AsmReleaseMPLock (&CpuData->StateLock);
+ break;
+ }
+
+ AsmReleaseMPLock (&CpuData->StateLock);
+
+ if (CheckTimeout (ExpectedTime)) {
+ ///
+ /// Save data into private data structure, and create timer to poll AP state before exiting
+ ///
+ mMPSystemData->WaitEvent = WaitEvent;
+ Status = gBS->SetTimer (
+ CpuData->CheckThisAPEvent,
+ TimerPeriodic,
+ CPU_CHECK_AP_INTERVAL * MICROSECOND
+ );
+ return EFI_TIMEOUT;
+ }
+
+ gBS->Stall (CPU_CHECK_AP_INTERVAL);
+ }
+
+ if (WaitEvent) gBS->SignalEvent (WaitEvent); //(AMI_CHG)
+ return EFI_SUCCESS;
+}
+
+/**
+ MP Service to get all the available application processors (APs)
+ to execute a caller-provided code stream.
+
+ @param[in] This - Pointer to MP Service Protocol
+ @param[in] Procedure - The procedure to be assigned to APs.
+ @param[in] SingleThread - If true, all APs execute in block mode.
+ Otherwise, all APs exceute in non-block mode.
+ @param[in] WaitEvent - If timeout, the event to be triggered after all APs finish.
+ @param[in] TimeoutInMicroSecs - The timeout value in microsecond. Zero means infinity.
+ @param[in] ProcArguments - Argument for Procedure.
+ @param[in] FailedCPUList - If not NULL, all APs that fail to start will be recorded in the list.
+
+ @retval EFI_INVALID_PARAMETER - Procudure is NULL.
+ @retval EFI_SUCCESS - Only 1 logical processor exists.
+ @retval EFI_SUCCESS - All APs have finished.
+ @retval EFI_TIMEOUT - Time goes out before all APs have finished.
+**/
+EFI_STATUS
+EFIAPI
+StartupAllAPs (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN BOOLEAN SingleThread,
+ IN EFI_EVENT WaitEvent OPTIONAL,
+ IN UINTN TimeoutInMicroSecs OPTIONAL,
+ IN OUT VOID *ProcArguments OPTIONAL,
+ OUT UINTN *FailedCPUList OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ CPU_DATA_BLOCK *CpuData;
+ CPU_DATA_BLOCK *NextCpuData;
+ UINTN ListIndex;
+ UINTN CpuNumber;
+ UINTN NextCpuNumber;
+ UINT64 ExpectedTime;
+ CPU_STATE APInitialState;
+ CPU_STATE CpuState;
+
+ ///
+ /// Check for valid procedure for APs
+ ///
+ if (Procedure == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (mMPSystemData->NumberOfCpus == 1) {
+ if (WaitEvent) gBS->SignalEvent (WaitEvent); //(AMI_CHG)
+ return EFI_SUCCESS;
+ }
+
+// AMI Override: Add
+ //
+ // Check whether all enabled APs are idle.
+ // If any enabled AP is not idle, return EFI_NOT_READY.
+ //
+ for (CpuNumber = 0; CpuNumber < mMPSystemData->NumberOfCpus; CpuNumber++) {
+
+ CpuData = &mMPSystemData->CpuData[CpuNumber];
+
+ //
+ // Skip BSP and disabled APs.
+ //
+ if (CpuNumber == mMPSystemData->BSP ||
+ CpuData->State == CPU_STATE_DISABLED) {
+ continue;
+ }
+
+ //
+ // If any enabled APs are busy, return EFI_NOT_FOUND.
+ //
+ if (CpuData->State != CPU_STATE_IDLE) {
+ return EFI_NOT_READY;
+ }
+ }
+ //
+ // All enabled APs are idle, we can safely initiate a new session
+ //
+// AMI Override: End
+ ExpectedTime = CalculateTimeout (TimeoutInMicroSecs);
+
+ ListIndex = 0;
+ CpuData = NULL;
+
+ mMPSystemData->FinishCount = 0;
+ mMPSystemData->StartCount = 0;
+ APInitialState = CPU_STATE_READY;
+
+ for (CpuNumber = 0; CpuNumber < mMPSystemData->NumberOfCpus; CpuNumber++) {
+ CpuData = &mMPSystemData->CpuData[CpuNumber];
+
+ ///
+ /// Get APs prepared, and put failing APs into FailedCPUList
+ /// If "SingleThread", one AP will be put to ready state.
+ /// Once this AP finishes its task, the next AP is put to Ready state.
+ /// This process continues until all APs are put into Ready State
+ /// if not "SingleThread", all APs are put to ready state at the same time
+ ///
+ if (CpuNumber != mMPSystemData->BSP) {
+ if (CpuData->State == CPU_STATE_IDLE) {
+ mMPSystemData->StartCount++;
+
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuData->State = APInitialState;
+ AsmReleaseMPLock (&CpuData->StateLock);
+
+ if (SingleThread) {
+ APInitialState = CPU_STATE_BLOCKED;
+ }
+
+ } else if (FailedCPUList != NULL) {
+ FailedCPUList[ListIndex] = CpuNumber;
+ ListIndex++;
+ }
+ }
+ }
+
+ while (TRUE) {
+ for (CpuNumber = 0; CpuNumber < mMPSystemData->NumberOfCpus; CpuNumber++) {
+ CpuData = &mMPSystemData->CpuData[CpuNumber];
+ if (CpuNumber == mMPSystemData->BSP) {
+ continue;
+ }
+ CpuState = CpuData->State;
+ switch (CpuState) {
+ case CPU_STATE_READY:
+ WakeUpAp (
+ CpuData,
+ Procedure,
+ ProcArguments
+ );
+ break;
+
+ case CPU_STATE_FINISHED:
+ mMPSystemData->FinishCount++;
+ if (SingleThread) {
+ Status = GetNextBlockedCpuNumber (&NextCpuNumber);
+ if (!EFI_ERROR (Status)) {
+ NextCpuData = &mMPSystemData->CpuData[NextCpuNumber];
+ AsmAcquireMPLock (&NextCpuData->StateLock);
+ NextCpuData->State = CPU_STATE_READY;
+ AsmReleaseMPLock (&NextCpuData->StateLock);
+ }
+ }
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuData->State = CPU_STATE_IDLE;
+ AsmReleaseMPLock (&CpuData->StateLock);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (mMPSystemData->FinishCount == mMPSystemData->StartCount) {
+ if (WaitEvent) gBS->SignalEvent (WaitEvent); //(AMI_CHG)
+ return EFI_SUCCESS;
+ }
+
+ if (CheckTimeout (ExpectedTime)) {
+ ///
+ /// Save data into private data structure, and create timer to poll AP state before exiting
+ ///
+ mMPSystemData->Procedure = Procedure;
+ mMPSystemData->ProcArguments = ProcArguments;
+ mMPSystemData->SingleThread = SingleThread;
+ mMPSystemData->WaitEvent = WaitEvent;
+
+ Status = gBS->SetTimer (
+ mMPSystemData->CheckAllAPsEvent,
+ TimerPeriodic,
+ CPU_CHECK_AP_INTERVAL * MICROSECOND
+ );
+ return EFI_TIMEOUT;
+ }
+
+ gBS->Stall (CPU_CHECK_AP_INTERVAL);
+ }
+
+ if (WaitEvent) gBS->SignalEvent (WaitEvent); //(AMI_CHG)
+ return EFI_SUCCESS;
+}
+
+/**
+ MP Service to makes the current BSP into an AP and then switches the
+ designated AP into the AP. This procedure is usually called after a CPU
+ test that has found that BSP is not healthy to continue it's responsbilities.
+
+ @param[in] This - Pointer to MP Service Protocol.
+ @param[in] CpuNumber - The number of the specified AP.
+ @param[in] EnableOldBSP - Whether to enable or disable the original BSP.
+
+ @retval EFI_INVALID_PARAMETER - Number for Specified AP out of range.
+ @retval EFI_INVALID_PARAMETER - Number of specified CPU belongs to BSP.
+ @retval EFI_NOT_READY - Specified AP is not idle.
+ @retval EFI_SUCCESS - BSP successfully switched.
+**/
+EFI_STATUS
+EFIAPI
+SwitchBSP (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN CpuNumber,
+ IN BOOLEAN EnableOldBSP
+ )
+{
+ EFI_STATUS Status;
+ EFI_CPU_ARCH_PROTOCOL *CpuArch;
+ BOOLEAN OldInterruptState;
+ CPU_DATA_BLOCK *CpuData;
+ CPU_STATE CpuState;
+
+ ///
+ /// Check if the specified CPU number is valid
+ ///
+ if (CpuNumber >= mMPSystemData->NumberOfCpus) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ///
+ /// Check if the specified CPU is already BSP
+ ///
+ if (CpuNumber == mMPSystemData->BSP) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CpuData = &mMPSystemData->CpuData[CpuNumber];
+ if (CpuData->State != CPU_STATE_IDLE) {
+ return EFI_NOT_READY;
+ }
+ ///
+ /// Before send both BSP and AP to a procedure to exchange their roles,
+ /// interrupt must be disabled. This is because during the exchange role
+ /// process, 2 CPU may use 1 stack. If interrupt happens, the stack will
+ /// be corrputed, since interrupt return address will be pushed to stack
+ /// by hardware.
+ ///
+ CpuArch = mMPSystemData->CpuArch;
+ (CpuArch->GetInterruptState)(CpuArch, &OldInterruptState);
+ if (OldInterruptState) {
+ Status = CpuArch->DisableInterrupt (CpuArch);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ ///
+ /// Unprogram virtual wire mode for the old BSP
+ ///
+ ProgramXApic (FALSE);
+ SetApicBSPBit (FALSE);
+
+ mMPSystemData->BSPInfo.State = CPU_SWITCH_STATE_IDLE;
+ mMPSystemData->BSPInfo.Lock = VacantFlag;
+ mMPSystemData->APInfo.State = CPU_SWITCH_STATE_IDLE;
+ mMPSystemData->APInfo.Lock = VacantFlag;
+
+ ///
+ /// Need to wakeUp AP (future BSP)
+ ///
+ WakeUpAp (
+ CpuData,
+ FutureBSPProc,
+ mMPSystemData
+ );
+
+ AsmExchangeRole (&mMPSystemData->BSPInfo, &mMPSystemData->APInfo);
+
+ ///
+ /// The new BSP has come out. Since it carries the register value of the AP, need
+ /// to pay attention to variable which are stored in registers (due to optimization)
+ ///
+ SetApicBSPBit (TRUE);
+ ProgramXApic (TRUE);
+
+ if (OldInterruptState) {
+ Status = CpuArch->EnableInterrupt (CpuArch);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ CpuData = &mMPSystemData->CpuData[mMPSystemData->BSP];
+ while (TRUE) {
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuState = CpuData->State;
+ AsmReleaseMPLock (&CpuData->StateLock);
+
+ if (CpuState == CPU_STATE_FINISHED) {
+ break;
+ }
+ }
+
+ Status = ChangeCpuState (mMPSystemData->BSP, EnableOldBSP, CPU_CAUSE_NOT_DISABLED);
+ mMPSystemData->BSP = CpuNumber;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure sends an IPI to the designated processor in
+ the requested delivery mode with the requested vector.
+
+ @param[in] This - Pointer to MP Service Protocol.
+ @param[in] CpuNumber - The number of the specified AP.
+ @param[in] VectorNumber - Vector number.
+ @param[in] DeliveryMode - I/O APIC Interrupt Deliver Modes
+
+ @retval EFI_INVALID_PARAMETER - Input paramters were not correct.
+ @retval Other status - Status returned by SendInterrupt ()
+**/
+EFI_STATUS
+EFIAPI
+SendIPI (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN CpuNumber,
+ IN UINTN VectorNumber,
+ IN UINTN DeliveryMode
+ )
+{
+ UINT32 TriggerMode;
+ EFI_STATUS Status;
+ CPU_DATA_BLOCK *CpuData;
+ MP_CPU_EXCHANGE_INFO *ExchangeInfo;
+ MONITOR_MWAIT_DATA *MonitorAddr;
+
+ ///
+ /// Check for valid input parameters.
+ ///
+ if (CpuNumber >= mMPSystemData->NumberOfCpus || CpuNumber == mMPSystemData->BSP) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (VectorNumber >= INTERRUPT_VECTOR_NUMBER) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (DeliveryMode >= DELIVERY_MODE_MAX) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CpuData = &mMPSystemData->CpuData[CpuNumber];
+ TriggerMode = TRIGGER_MODE_EDGE;
+
+ ///
+ /// Fix the vector number for special interrupts like SMI and INIT.
+ ///
+ if (DeliveryMode == DELIVERY_MODE_SMI || DeliveryMode == DELIVERY_MODE_INIT) {
+ VectorNumber = 0x0;
+ }
+
+ ///
+ /// If current waking manner is not HLT loop and some other DXE driver
+ /// like as TXT needs to send INIT command per this MpService routine,
+ /// then we need to set vector change flag for the specific AP to back
+ /// to MWAIT or RUN loop procedure, so additional INIT-SIPI command
+ /// will be sent in WakeUpAp routine for AP tasks to work later.
+ ///
+ ExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (mAcpiCpuData->WakeUpBuffer + MP_CPU_EXCHANGE_INFO_OFFSET);
+ if (ExchangeInfo->WakeUpApManner != WakeUpApPerHltLoop && DeliveryMode == DELIVERY_MODE_INIT) {
+ MonitorAddr = (MONITOR_MWAIT_DATA *)
+ (
+ (UINT8 *) ExchangeInfo->StackStart +
+ (ExchangeInfo->BistBuffer[CpuData->ApicID].Number + 1) *
+ ExchangeInfo->StackSize -
+ MONITOR_FILTER_SIZE
+ );
+ MonitorAddr->WakeUpApVectorChangeFlag = TRUE;
+ }
+
+ Status = SendInterrupt (
+ BROADCAST_MODE_SPECIFY_CPU,
+ CpuData->ApicID,
+ (UINT32) VectorNumber,
+ (UINT32) DeliveryMode,
+ TriggerMode,
+ TRUE
+ );
+
+ return Status;
+}
+
+/**
+ This procedure enables Or disables APs.
+
+ @param[in] This - Pointer to MP Service Protocol.
+ @param[in] CpuNumber - The number of the specified AP.
+ @param[in] NewAPState - Indicate new desired AP state
+ @param[in] HealthState - If not NULL, it points to the value that specifies
+ the new health status of the AP. If it is NULL,
+ this parameter is ignored.
+
+ @retval EFI_INVALID_PARAMETER - Input paramters were not correct.
+ @retval EFI_SUCCESS - Function completed successfully
+**/
+EFI_STATUS
+EFIAPI
+EnableDisableAP (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN CpuNumber,
+ IN BOOLEAN NewAPState,
+ IN EFI_MP_HEALTH *HealthState OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ CPU_DATA_BLOCK *CpuData;
+
+ ///
+ /// Check for valid input parameters.
+ ///
+ if (CpuNumber >= mMPSystemData->NumberOfCpus || CpuNumber == mMPSystemData->BSP) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CpuData = &mMPSystemData->CpuData[CpuNumber];
+ Status = ChangeCpuState (CpuNumber, NewAPState, CPU_CAUSE_USER_SELECTION);
+
+ if (HealthState != NULL) {
+ CopyMem (&CpuData->Health, HealthState, sizeof (EFI_MP_HEALTH));
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure returns the calling CPU handle.
+
+ @param[in] This - Pointer to MP Service Protocol.
+ @param[in] CpuNumber - The number of the specified AP.
+
+ @retval EFI_SUCCESS - Function completed successfully
+**/
+EFI_STATUS
+EFIAPI
+WhoAmI (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ OUT UINTN *CpuNumber
+ )
+{
+ UINTN ApicID;
+ UINTN NumOfCpus;
+ UINTN Index;
+
+ ApicID = GetApicID (NULL, NULL);
+
+ NumOfCpus = mMPSystemData->NumberOfCpus;
+
+ for (Index = 0; Index < NumOfCpus; Index++) {
+ if (ApicID == mMPSystemData->CpuData[Index].ApicID) {
+ break;
+ }
+ }
+
+ *CpuNumber = Index;
+ return EFI_SUCCESS;
+}
+
+/**
+ Searches the HOB list provided by the core to find
+ if a MP guided HOB list exists or not. If it does, it copies it to the driver
+ data area, else returns 0
+
+ @param[in] MPSystemData - Pointer to an MP_SYSTEM_DATA structure
+
+ @retval EFI_SUCCESS - Success
+ @retval EFI_NOT_FOUND - HOB not found or else
+**/
+EFI_STATUS
+GetMpBistStatus (
+ IN MP_SYSTEM_DATA *MPSystemData
+ )
+{
+ VOID *HobList;
+ VOID *DataInHob;
+ EFI_PEI_HOB_POINTERS Hob;
+ UINTN DataSize;
+
+ ///
+ /// Check for MP Data Hob.
+ ///
+ HobList = GetFirstGuidHob (&gEfiHtBistHobGuid);
+
+ if (HobList == NULL) {
+ DEBUG ((EFI_D_ERROR, "No HOBs found\n"));
+ return EFI_NOT_FOUND;
+ }
+
+ DataInHob = (VOID *) ((UINTN) HobList + sizeof (EFI_HOB_GUID_TYPE));
+
+ Hob.Header = HobList;
+ DataSize = Hob.Header->HobLength - sizeof (EFI_HOB_GUID_TYPE);
+
+ ///
+ /// This is the MP HOB. So, copy all the data
+ ///
+ if (HobList != NULL) {
+ if (NULL == MPSystemData->BistHobData) {
+ (gBS->AllocatePool)(EfiReservedMemoryType, DataSize, (VOID **) &MPSystemData->BistHobData);
+ }
+
+ CopyMem (MPSystemData->BistHobData, DataInHob, DataSize);
+ MPSystemData->BistHobSize = DataSize;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Check if CPUID support large than 3
+
+ @retval TRUE if CPUID support large than 3
+ @retval FALSE if not
+**/
+BOOLEAN
+IsCpuidSupportOver3 (
+ VOID
+ )
+{
+ BOOLEAN RetVal;
+ EFI_CPUID_REGISTER CpuidRegisters;
+ RetVal = FALSE;
+ AsmCpuid (
+ CPUID_SIGNATURE,
+ &CpuidRegisters.RegEax,
+ &CpuidRegisters.RegEbx,
+ &CpuidRegisters.RegEcx,
+ &CpuidRegisters.RegEdx
+ );
+ if (CpuidRegisters.RegEax > 3) {
+ RetVal = TRUE;
+ }
+
+ return RetVal;
+}
+
+/**
+ Allocate data pool for MP information and fill data in it.
+
+ @param[in] WakeUpBuffer - The address of wakeup buffer.
+ @param[in] StackAddressStart - The start address of APs's stacks.
+ @param[in] MaximumCPUsForThisSystem - Maximum CPUs in this system.
+
+ @retval EFI_SUCCESS - Function successfully executed.
+ @retval Other - Error occurred while allocating memory.
+**/
+EFI_STATUS
+FillMPData (
+ OUT EFI_PHYSICAL_ADDRESS WakeUpBuffer,
+ OUT VOID *StackAddressStart,
+ IN UINTN MaximumCPUsForThisSystem
+ )
+{
+ EFI_STATUS Status;
+
+ ///
+ /// First check if the MP data structures and AP rendezvous routine have been
+ /// supplied by the PEIMs that executed in early boot stage.
+ ///
+ ///
+ /// Clear the data structure area first.
+ ///
+ ZeroMem (mMPSystemData, sizeof (MP_SYSTEM_DATA));
+
+ Status = GetMpBistStatus (mMPSystemData);
+
+ mAcpiCpuData->CpuPrivateData = (EFI_PHYSICAL_ADDRESS) (UINTN) (&(mMPSystemData->S3DataPointer));
+ mAcpiCpuData->APState = mPlatformCpu->CpuConfig->HtState;
+ mAcpiCpuData->WakeUpBuffer = WakeUpBuffer;
+ mAcpiCpuData->StackAddress = (EFI_PHYSICAL_ADDRESS) StackAddressStart;
+
+ Status = PrepareGdtIdtForAP (
+ (PSEUDO_DESCRIPTOR *) (UINTN) mAcpiCpuData->GdtrProfile,
+ (PSEUDO_DESCRIPTOR *) (UINTN) mAcpiCpuData->IdtrProfile
+ );
+
+ ///
+ /// First BSP fills and inits all known values, including it's own records.
+ ///
+ mMPSystemData->APSerializeLock = VacantFlag;
+ mMPSystemData->NumberOfCpus = 1;
+ mMPSystemData->EnableSecondaryCpu = mPlatformCpu->CpuConfig->HtState;
+
+ ///
+ /// Record these CPU configuration data (both for normal boot and for S3 use)
+ ///
+ if (IsCpuidSupportOver3 ()) {
+ mMPSystemData->LimitCpuidMaximumValue = mPlatformCpu->CpuConfig->LimitCpuidMaximumValue;
+ } else {
+ mMPSystemData->LimitCpuidMaximumValue = FALSE;
+ }
+
+ mMPSystemData->ExecuteDisableBit = mPlatformCpu->CpuConfig->ExecuteDisableBit;
+ mMPSystemData->VmxEnable = mPlatformCpu->CpuConfig->VmxEnable;
+ mMPSystemData->TxtEnable = mPlatformCpu->CpuConfig->SmxEnable;
+ mMPSystemData->MonitorMwaitEnable = mPlatformCpu->CpuConfig->MonitorMwaitEnable;
+ mMPSystemData->MachineCheckEnable = mPlatformCpu->CpuConfig->MachineCheckEnable;
+ mMPSystemData->XapicEnable = mPlatformCpu->CpuConfig->XapicEnable;
+ mMPSystemData->AesEnable = mPlatformCpu->CpuConfig->AesEnable;
+ mMPSystemData->DebugInterfaceEnable = 0;
+ mMPSystemData->DebugInterfaceLockEnable = 1;
+ if (mPlatformCpu->Revision >= DXE_PLATFORM_CPU_POLICY_PROTOCOL_REVISION_2) {
+ mMPSystemData->DebugInterfaceEnable = mPlatformCpu->CpuConfig->DebugInterfaceEnable;
+ mMPSystemData->DebugInterfaceLockEnable = mPlatformCpu->CpuConfig->DebugInterfaceLockEnable;
+ }
+
+ mMPSystemData->S3DataPointer.S3BootScriptTable = (UINT32) (UINTN) mMPSystemData->S3BootScriptTable;
+ mMPSystemData->S3DataPointer.S3BspMtrrTable = (UINT32) (UINTN) mMPSystemData->S3BspMtrrTable;
+
+ mMPSystemData->CpuArch = NULL;
+ gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **) &mMPSystemData->CpuArch);
+
+ mMPSystemData->MaximumCpusForThisSystem = MaximumCPUsForThisSystem;
+
+ mMPSystemData->BSP = 0;
+
+ ///
+ /// Save Mtrr Register for S3 resume
+ ///
+ SaveBspMtrrForS3 ();
+
+ FillInProcessorInformation (mMPSystemData, TRUE, 0);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Wake up APs for the first time to count their number and collect BIST data.
+
+ @param[in] WakeUpBuffer - Address of the wakeup buffer.
+
+ @retval EFI_SUCCESS - Function successfully finishes.
+**/
+EFI_STATUS
+CountApNumberAndCollectBist (
+ IN EFI_PHYSICAL_ADDRESS WakeUpBuffer
+ )
+{
+ MP_CPU_EXCHANGE_INFO *ExchangeInfo;
+ UINTN Index;
+ UINT64 MsrValue;
+ UINT64 ProcessorThreadCount;
+ UINT32 ResponseProcessorCount;
+ UINTN TimeoutTime;
+
+ ///
+ /// Send INIT IPI - SIPI to all APs
+ ///
+ SendInterrupt (
+ BROADCAST_MODE_ALL_EXCLUDING_SELF,
+ 0,
+ 0,
+ DELIVERY_MODE_INIT,
+ TRIGGER_MODE_EDGE,
+ TRUE
+ );
+ gBS->Stall (10 * STALL_ONE_MILLI_SECOND);
+ SendInterrupt (
+ BROADCAST_MODE_ALL_EXCLUDING_SELF,
+ 0,
+ (UINT32) RShiftU64 (WakeUpBuffer,
+ 12),
+ DELIVERY_MODE_SIPI,
+ TRIGGER_MODE_EDGE,
+ TRUE
+ );
+ gBS->Stall (200 * STALL_ONE_MICRO_SECOND);
+ SendInterrupt (
+ BROADCAST_MODE_ALL_EXCLUDING_SELF,
+ 0,
+ (UINT32) RShiftU64 (WakeUpBuffer,
+ 12),
+ DELIVERY_MODE_SIPI,
+ TRIGGER_MODE_EDGE,
+ TRUE
+ );
+ gBS->Stall (200 * STALL_ONE_MICRO_SECOND);
+ ExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (WakeUpBuffer + MP_CPU_EXCHANGE_INFO_OFFSET);
+
+ ///
+ /// Get thread count
+ ///
+ MsrValue = AsmReadMsr64 (MSR_CORE_THREAD_COUNT);
+ ProcessorThreadCount = MsrValue & 0xffff;
+
+ ///
+ /// Only support MAXIMUM_CPU_NUMBER threads so far
+ ///
+ ASSERT (ProcessorThreadCount <= MAXIMUM_CPU_NUMBER);
+ if (ProcessorThreadCount > MAXIMUM_CPU_NUMBER) {
+ ProcessorThreadCount = MAXIMUM_CPU_NUMBER;
+ }
+
+ for (TimeoutTime = 0; TimeoutTime <= CPU_WAIT_FOR_TASK_TO_BE_COMPLETED; TimeoutTime += CPU_CHECK_AP_INTERVAL) {
+ ///
+ /// Wait for task to complete and then exit.
+ ///
+ gBS->Stall (CPU_CHECK_AP_INTERVAL);
+ for (Index = 1, ResponseProcessorCount = 1; Index < MAXIMUM_CPU_NUMBER; Index++) {
+ if (ExchangeInfo->BistBuffer[Index].Number == 1) {
+ ResponseProcessorCount++;
+ }
+ }
+
+ if (ResponseProcessorCount == ProcessorThreadCount) {
+ break;
+ }
+ }
+
+ for (Index = 0; Index < MAXIMUM_CPU_NUMBER; Index++) {
+ if (ExchangeInfo->BistBuffer[Index].Number == 1) {
+ ExchangeInfo->BistBuffer[Index].Number = (UINT32) mMPSystemData->NumberOfCpus++;
+ }
+ }
+
+ mAcpiCpuData->NumberOfCpus = (UINT32) mMPSystemData->NumberOfCpus;
+
+ ExchangeInfo->InitFlag = 0;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Wake up APs for the second time to collect detailed information.
+
+ @param[in] WakeUpBuffer - Address of the wakeup buffer.
+
+ @retval EFI_SUCCESS - Function successfully finishes.
+**/
+EFI_STATUS
+PollForInitialization (
+ IN EFI_PHYSICAL_ADDRESS WakeUpBuffer
+ )
+{
+ MP_CPU_EXCHANGE_INFO *ExchangeInfo;
+ UINT32 FailedRevision;
+ EFI_STATUS Status;
+
+ ExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (WakeUpBuffer + MP_CPU_EXCHANGE_INFO_OFFSET);
+
+ ExchangeInfo->ApFunction = (VOID *) (UINTN) DetailedMpInitialization;
+
+ CpuInitFloatPointUnit ();
+
+ ///
+ /// Update microcode for BSP
+ ///
+ mMcuLoadCount = 0;
+ Status = InitializeMicrocode (mMicrocodePointerBuffer, &FailedRevision);
+ if (Status == EFI_LOAD_ERROR) {
+ DEBUG((EFI_D_INFO,"Failed to load microcode patch\n"));
+ }
+
+ ///
+ /// Wait until all APs finish
+ ///
+ while (mFinishedCount < mAcpiCpuData->NumberOfCpus - 1) {
+ CpuPause ();
+ }
+
+ McuFirstLoadDone ();
+ return EFI_SUCCESS;
+}
+
+/**
+ Callback function to initialize MP data hub
+
+ @param[in] Event - Event whose notification function is being invoked.
+ @param[in] Context - Pointer to the notification functions context, which is implementation dependent.
+**/
+VOID
+EFIAPI
+MpDataHubCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ CPU_DATA_FOR_DATAHUB *CpuDataforDatahub;
+ UINTN Index;
+ EFI_STATUS Status;
+
+ Status = InitializeDataHubPtr (&mDataHub);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ for (Index = 0; Index < mMPSystemData->NumberOfCpus; Index++) {
+ CpuDataforDatahub = &mMPSystemData->CpuData[Index].CpuDataforDatahub;
+ UpdateDataforDatahub (Index, CpuDataforDatahub);
+ }
+
+}
+
+/**
+ Initialize multiple processors and collect MP related data
+
+ @retval EFI_SUCCESS - Multiple processors get initialized and data collected successfully
+ @retval Other - The operation failed and appropriate error status will be returned
+**/
+EFI_STATUS
+InitializeMpSystemData (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 MaxThreadsPerCore;
+ UINT32 MaxCoresPerDie;
+ UINT32 MaxDiesPerPackage;
+ UINT32 MaxPackages;
+
+ VOID *StackAddressStart;
+ EFI_PHYSICAL_ADDRESS WakeUpBuffer;
+ MP_CPU_EXCHANGE_INFO *ExchangeInfo;
+ UINTN Index;
+
+ EFI_CPU_ARCH_PROTOCOL *CpuArch;
+ BOOLEAN mInterruptState;
+ CPU_DATA_BLOCK *CpuData;
+ UINTN MaximumCPUsForThisSystem;
+ VOID *Registration;
+ EFI_HANDLE Handle;
+
+ Handle = NULL;
+
+ ///
+ /// Program Local APIC registers
+ ///
+ ProgramXApic (TRUE);
+
+ ///
+ /// Get information on threads, cores, dies and package for the CPU(s) on this platform
+ ///
+ Status = mPlatformCpu->CpuConfig->GetMaxCount (
+ mPlatformCpu,
+ &MaxThreadsPerCore,
+ &MaxCoresPerDie,
+ &MaxDiesPerPackage,
+ &MaxPackages
+ );
+ ///
+ /// Get the total CPU count
+ ///
+ if (!EFI_ERROR (Status)) {
+ MaximumCPUsForThisSystem = MaxThreadsPerCore * MaxCoresPerDie * MaxDiesPerPackage * MaxPackages;
+ } else {
+ MaximumCPUsForThisSystem = MAXIMUM_CPU_NUMBER;
+ }
+
+ ///
+ /// Prepare Wakeup Buffer and Stack for APs
+ ///
+ Status = PrepareMemoryForAPs (
+ &WakeUpBuffer,
+ &StackAddressStart,
+ MaximumCPUsForThisSystem
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ mOriginalBuffer = WakeUpBuffer;
+ Status = (gBS->AllocatePages)(AllocateAnyPages, EfiBootServicesData, 1, &mBackupBuffer);
+
+ ///
+ /// Fill MP Data
+ ///
+ FillMPData (
+ WakeUpBuffer,
+ StackAddressStart,
+ MaximumCPUsForThisSystem
+ );
+
+ ///
+ /// Prepare exchange information for APs
+ ///
+ ExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (WakeUpBuffer + MP_CPU_EXCHANGE_INFO_OFFSET);
+ PrepareExchangeInfo (
+ ExchangeInfo,
+ StackAddressStart,
+ NULL,
+ WakeUpBuffer
+ );
+
+ ReportStatusCode (
+ EFI_PROGRESS_CODE,
+ EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_PC_AP_INIT
+ );
+
+ CpuArch = mMPSystemData->CpuArch;
+ (CpuArch->GetInterruptState)(CpuArch, &mInterruptState);
+ CpuArch->DisableInterrupt (CpuArch);
+
+ ///
+ /// Get BSP Performance Control setting
+ ///
+ mCpuPerfCtrlValue = AsmReadMsr64 (MSR_IA32_PERF_CTRL);
+
+#ifdef BOOT_GUARD_SUPPORT_FLAG
+ //
+ // Disable PBET before send IPI to APs
+ //
+ StopPbeTimer ();
+#endif
+
+ ///
+ /// First INIT-SIPI-SIPI and reset AP waking counters
+ ///
+ CountApNumberAndCollectBist (WakeUpBuffer);
+ ExchangeInfo->WakeUpApManner = WakeUpApCounterInit;
+
+ ///
+ /// Assign AP function to initialize FPU MCU MTRR and get detail info
+ ///
+ PollForInitialization (WakeUpBuffer);
+ ///
+ /// Assign WakeUpApManner (WakeUpApPerHltLoop/WakeUpApPerMwaitLoop/WakeUpApPerRunLoop)
+ ///
+ ExchangeInfo->WakeUpApManner = mPlatformCpu->CpuConfig->ApIdleManner;
+ ///
+ /// Assign AP function to ApProcWrapper for StartAllAps/StartThisAp calling
+ ///
+ ExchangeInfo->ApFunction = (VOID *) (UINTN) ApProcWrapper;
+
+ if (mInterruptState) {
+ CpuArch->EnableInterrupt (CpuArch);
+ }
+
+ for (Index = 1; Index < mMPSystemData->NumberOfCpus; Index++) {
+ CpuData = &mMPSystemData->CpuData[Index];
+ if (CpuData->Health.Uint32 != 0) {
+ ReportStatusCode (
+ EFI_ERROR_MAJOR | EFI_ERROR_CODE,
+ EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_EC_SELF_TEST
+ );
+ }
+
+ Status = CheckMicrocodeUpdate (Index, CpuData->MicrocodeStatus, CpuData->FailedRevision);
+ if (Status == EFI_LOAD_ERROR) {
+ DEBUG((EFI_D_INFO,"Failed to load microcode patch\n"));
+ }
+ }
+
+ Status = gBS->CreateEvent (
+ EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,
+ EFI_TPL_CALLBACK,
+ CheckAllAPsStatus,
+ NULL,
+ &mMPSystemData->CheckAllAPsEvent
+ );
+ for (Index = 0; Index < mMPSystemData->NumberOfCpus; Index++) {
+ CpuData = &mMPSystemData->CpuData[Index];
+ if (Index == mMPSystemData->BSP) {
+ continue;
+ }
+ Status = gBS->CreateEvent (
+ EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,
+ EFI_TPL_CALLBACK,
+ CheckThisAPStatus,
+ (VOID *) CpuData,
+ &CpuData->CheckThisAPEvent
+ );
+ }
+ ///
+ /// Switch BSP to Lowest Feature Processor (LFP)
+ ///
+ if (mPlatformCpu->CpuConfig->BspSelection == 16) {
+ Status = SwitchToLowestFeatureProcess (&mMpService);
+ }
+
+ ///
+ /// Initialize feature control structure
+ ///
+ InitializeFeaturePerSetup (mMPSystemData);
+
+ ///
+ /// Detect and log all processor supported features
+ ///
+ CollectProcessorFeature (&mMpService);
+ Status = mMpService.StartupAllAPs (
+ &mMpService,
+ CollectProcessorFeature,
+ FALSE,
+ NULL,
+ 0,
+ (VOID *) &mMpService,
+ NULL
+ );
+
+ ProgramProcessorFeature (&mMpService);
+ Status = mMpService.StartupAllAPs (
+ &mMpService,
+ ProgramProcessorFeature,
+ FALSE,
+ NULL,
+ 0,
+ (VOID *) &mMpService,
+ NULL
+ );
+
+ ///
+ /// Install CPU info protocol
+ ///
+ mCpuInfo.Revision = DXE_CPU_INFO_REVISION_1;
+ mCpuInfo.RcVersion = CPU_RC_VERSION;
+ mCpuInfo.CpuCommonFeatures = mCommonFeatures;
+
+ gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gDxeCpuInfoProtocolGuid,
+ &mCpuInfo,
+ NULL
+ );
+ DEBUG ((EFI_D_INFO, "mCommonFeatures = %x\n", mCommonFeatures));
+
+ EfiCreateProtocolNotifyEvent (
+ &gEfiDataHubProtocolGuid,
+ EFI_TPL_CALLBACK,
+ MpDataHubCallback,
+ NULL,
+ &Registration
+ );
+
+ CopyMem ((VOID *) (UINTN) mBackupBuffer, (VOID *) (UINTN) mOriginalBuffer, EFI_PAGE_SIZE);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Wrapper function for all procedures assigned to AP via MP service protocol.
+ It controls states of AP and invokes assigned precedure.
+**/
+VOID
+ApProcWrapper (
+ VOID
+ )
+{
+ EFI_AP_PROCEDURE Procedure;
+ VOID *Parameter;
+ UINTN CpuNumber;
+ CPU_DATA_BLOCK *CpuData;
+ MP_CPU_EXCHANGE_INFO *ExchangeInfo;
+ MONITOR_MWAIT_DATA *MonitorAddr;
+
+ ///
+ /// Initialize MCE for CR4.
+ ///
+ InitializeMce (mMPSystemData->MachineCheckEnable);
+
+ WhoAmI (&mMpService, &CpuNumber);
+ CpuData = &mMPSystemData->CpuData[CpuNumber];
+
+ ///
+ /// Now let us check it out.
+ ///
+ Procedure = CpuData->Procedure;
+ Parameter = CpuData->Parameter;
+
+ if (Procedure != NULL) {
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuData->State = CPU_STATE_BUSY;
+ AsmReleaseMPLock (&CpuData->StateLock);
+ Procedure (Parameter);
+
+ ///
+ /// if BSP is switched to AP, it continue execute from here, but it carries register state
+ /// of the old AP, so need to reload CpuData (might be stored in a register after compiler
+ /// optimization) to make sure it points to the right data
+ ///
+ WhoAmI (&mMpService, &CpuNumber);
+ CpuData = &mMPSystemData->CpuData[CpuNumber];
+
+ AsmAcquireMPLock (&CpuData->ProcedureLock);
+ CpuData->Procedure = NULL;
+ AsmReleaseMPLock (&CpuData->ProcedureLock);
+
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuData->State = CPU_STATE_FINISHED;
+ AsmReleaseMPLock (&CpuData->StateLock);
+
+ ///
+ /// Check AP wakeup manner, update signal and relating counter once finishing AP task
+ ///
+ ExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (mAcpiCpuData->WakeUpBuffer + MP_CPU_EXCHANGE_INFO_OFFSET);
+ MonitorAddr = (MONITOR_MWAIT_DATA *)
+ (
+ (UINT8 *) ExchangeInfo->StackStart +
+ (ExchangeInfo->BistBuffer[CpuData->ApicID].Number + 1) *
+ ExchangeInfo->StackSize -
+ MONITOR_FILTER_SIZE
+ );
+
+ switch (ExchangeInfo->WakeUpApManner) {
+ case WakeUpApPerHltLoop:
+ MonitorAddr->HltLoopBreakCounter += 1;
+ break;
+
+ case WakeUpApPerMwaitLoop:
+ MonitorAddr->MwaitLoopBreakCounter += 1;
+ break;
+
+ case WakeUpApPerRunLoop:
+ MonitorAddr->RunLoopBreakCounter += 1;
+ break;
+
+ case WakeUpApPerMwaitLoop32:
+ MonitorAddr->MwaitLoopBreakCounter32 += 1;
+ break;
+
+ case WakeUpApPerRunLoop32:
+ MonitorAddr->RunLoopBreakCounter32 += 1;
+ break;
+
+ default:
+ break;
+ }
+
+ MonitorAddr->BreakToRunApSignal = 0;
+ }
+}
+
+/**
+ Procedure for detailed initialization of APs. It will be assigned to all APs
+ after first INIT-SIPI-SIPI finishing CPU number counting and BIST collection.
+**/
+VOID
+DetailedMpInitialization (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 FailedRevision;
+
+ ///
+ /// Program APs CPU Performance Control setting
+ ///
+ AsmWriteMsr64 (MSR_IA32_PERF_CTRL, mCpuPerfCtrlValue);
+
+ CpuInitFloatPointUnit ();
+
+ Status = InitializeMicrocode (
+ (EFI_CPU_MICROCODE_HEADER **) (UINTN) mAcpiCpuData->MicrocodePointerBuffer,
+ &FailedRevision
+ );
+
+ ///
+ /// Init MLC Streamer Prefetcher and MLC Spatial Prefetcher
+ ///
+ InitializeProcessorsPrefetcher (
+ mPlatformCpu->CpuConfig->MlcStreamerPrefetcher,
+ mPlatformCpu->CpuConfig->MlcSpatialPrefetcher
+ );
+
+ ///
+ /// Init Cache after all MCU is loaded
+ ///
+ while (mMcuLoadCount < mAcpiCpuData->NumberOfCpus) {
+ CpuPause ();
+ }
+
+ ///
+ /// Save Mtrr Registers in global data areas
+ ///
+ MpMtrrSynchUp (NULL);
+ ProgramXApic (FALSE);
+ FillInProcessorInformation (mMPSystemData, FALSE, 0);
+ InterlockedIncrement (&mFinishedCount);
+}
+
+/**
+ Switch current BSP processor to AP
+
+ @param[in] MPSystemData - Pointer to the data structure containing MP related data
+**/
+VOID
+FutureBSPProc (
+ IN MP_SYSTEM_DATA *MPSystemData
+ )
+{
+ AsmExchangeRole (&MPSystemData->APInfo, &MPSystemData->BSPInfo);
+ return;
+}
+
+/**
+ This function is called by all processors (both BSP and AP) once and collects MP related data
+
+ @param[in] MPSystemData - Pointer to the data structure containing MP related data
+ @param[in] BSP - TRUE if the CPU is BSP
+ @param[in] BistParam - BIST (build-in self test) data for the processor. This data
+ is only valid for processors that are waked up for the 1ast
+ time in this CPU DXE driver.
+
+ @retval EFI_SUCCESS - Data for the processor collected and filled in
+**/
+EFI_STATUS
+FillInProcessorInformation (
+ IN MP_SYSTEM_DATA *MPSystemData,
+ IN BOOLEAN BSP,
+ IN UINT32 BistParam
+ )
+{
+ UINT32 Health;
+ UINT32 ApicID;
+ CPU_DATA_BLOCK *CpuData;
+ UINT32 BIST;
+ UINTN CpuNumber;
+ UINTN Index;
+ UINTN Count;
+ MP_CPU_EXCHANGE_INFO *ExchangeInfo;
+
+ ApicID = GetApicID (NULL, NULL);
+ BIST = 0;
+
+ if (BSP) {
+ CpuNumber = 0;
+ BIST = BistParam;
+ } else {
+ ExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (mAcpiCpuData->WakeUpBuffer + MP_CPU_EXCHANGE_INFO_OFFSET);
+ CpuNumber = ExchangeInfo->BistBuffer[ApicID].Number;
+ BIST = ExchangeInfo->BistBuffer[ApicID].BIST;
+ }
+
+ CpuData = &MPSystemData->CpuData[CpuNumber];
+ CpuData->SecondaryCpu = IsSecondaryThread ();
+ CpuData->ApicID = ApicID;
+ CpuData->Procedure = NULL;
+ CpuData->Parameter = NULL;
+ CpuData->StateLock = VacantFlag;
+ CpuData->ProcedureLock = VacantFlag;
+ CpuData->State = CPU_STATE_IDLE;
+
+ Health = BIST;
+ Count = MPSystemData->BistHobSize / sizeof (BIST_HOB_DATA);
+ for (Index = 0; Index < Count; Index++) {
+ if (ApicID == MPSystemData->BistHobData[Index].ApicId) {
+ Health = MPSystemData->BistHobData[Index].Health.Uint32;
+ }
+ }
+
+ if (Health > 0) {
+ CpuData->State = CPU_STATE_DISABLED;
+ MPSystemData->DisableCause[CpuNumber] = CPU_CAUSE_SELFTEST_FAILURE;
+
+ } else {
+ MPSystemData->DisableCause[CpuNumber] = CPU_CAUSE_NOT_DISABLED;
+ }
+
+ FillinDataforDataHub (CpuNumber, &CpuData->CpuDataforDatahub);
+ CpuData->CpuDataforDatahub.Health.Uint32 = Health;
+
+ CopyMem (&CpuData->PhysicalLocation, &CpuData->CpuDataforDatahub.Location, sizeof (PHYSICAL_LOCATION));
+ return EFI_SUCCESS;
+}
+
+/**
+ Set APIC BSP bit
+
+ @param[in] Enable - enable as BSP or not
+
+ @retval EFI_SUCCESS - always return success
+**/
+EFI_STATUS
+SetApicBSPBit (
+ IN BOOLEAN Enable
+ )
+{
+ UINT64 ApicBaseReg;
+
+ ApicBaseReg = AsmReadMsr64 (MSR_IA32_APIC_BASE);
+
+ if (Enable) {
+ ApicBaseReg |= 0x100;
+ } else {
+ ApicBaseReg &= 0xfffffffffffffe00;
+ }
+
+ AsmWriteMsr64 (MSR_IA32_APIC_BASE, ApicBaseReg);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Change CPU state
+
+ @param[in] CpuNumber - CPU number
+ @param[in] NewState - the new state that will be changed to
+ @param[in] Cause - Cause
+
+ @retval EFI_SUCCESS - always return success
+**/
+EFI_STATUS
+ChangeCpuState (
+ IN UINTN CpuNumber,
+ IN BOOLEAN NewState,
+ IN CPU_STATE_CHANGE_CAUSE Cause
+ )
+{
+ CPU_DATA_BLOCK *CpuData;
+ EFI_COMPUTING_UNIT_CPU_DISABLED_ERROR_DATA ErrorData;
+
+ CpuData = &mMPSystemData->CpuData[CpuNumber];
+
+ mMPSystemData->DisableCause[CpuNumber] = Cause;
+
+ if (!NewState) {
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuData->State = CPU_STATE_DISABLED;
+ AsmReleaseMPLock (&CpuData->StateLock);
+
+ ErrorData.DataHeader.HeaderSize = sizeof (EFI_STATUS_CODE_DATA);
+ ErrorData.DataHeader.Size = sizeof (EFI_COMPUTING_UNIT_CPU_DISABLED_ERROR_DATA) - sizeof (EFI_STATUS_CODE_DATA);
+ CopyMem (
+ &ErrorData.DataHeader.Type,
+ &gEfiStatusCodeSpecificDataGuid,
+ sizeof (EFI_GUID)
+ );
+ ErrorData.Cause = Cause;
+ ErrorData.SoftwareDisabled = TRUE;
+//(AMI_CHG)>
+/* ReportStatusCode (
+ EFI_ERROR_MINOR | EFI_ERROR_CODE,
+ EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_EC_DISABLED
+ );*/
+//<(AMI_CHG)
+ } else {
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuData->State = CPU_STATE_IDLE;
+ AsmReleaseMPLock (&CpuData->StateLock);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Check if this is non-core processor - HT AP thread
+
+ @retval TRUE if this is HT AP thread
+ @retval FALSE if this is core thread
+**/
+BOOLEAN
+IsSecondaryThread (
+ VOID
+ )
+{
+ UINT32 ApicID;
+ EFI_CPUID_REGISTER CpuidRegisters;
+ UINT8 CpuCount;
+ UINT8 CoreCount;
+ UINT8 CpuPerCore;
+ UINT32 Mask;
+
+ ApicID = GetApicID (NULL, NULL);
+
+ AsmCpuid (
+ CPUID_VERSION_INFO,
+ &CpuidRegisters.RegEax,
+ &CpuidRegisters.RegEbx,
+ &CpuidRegisters.RegEcx,
+ &CpuidRegisters.RegEdx
+ );
+ if ((CpuidRegisters.RegEdx & 0x10000000) == 0) {
+ return FALSE;
+ }
+
+ CpuCount = (UINT8) ((CpuidRegisters.RegEbx >> 16) & 0xff);
+ if (CpuCount == 1) {
+ return FALSE;
+ }
+
+ AsmCpuid (
+ CPUID_SIGNATURE,
+ &CpuidRegisters.RegEax,
+ &CpuidRegisters.RegEbx,
+ &CpuidRegisters.RegEcx,
+ &CpuidRegisters.RegEdx
+ );
+ if (CpuidRegisters.RegEax > 3) {
+
+ CoreCount = GetCoreNumber ();
+ } else {
+ CoreCount = 1;
+ }
+
+ ///
+ /// Assumes there is symmetry across core boundary, i.e. each core within a package has the same number of logical processors
+ ///
+ if (CpuCount == CoreCount) {
+ return FALSE;
+ }
+
+ CpuPerCore = CpuCount / CoreCount;
+
+ ///
+ /// Assume 1 Core has no more than 8 threads
+ ///
+ if (CpuPerCore == 2) {
+ Mask = 0x1;
+ } else if (CpuPerCore <= 4) {
+ Mask = 0x3;
+ } else {
+ Mask = 0x7;
+ }
+
+ if ((ApicID & Mask) == 0) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+/**
+ If timeout occurs in StartupAllAps(), a timer is set, which invokes this
+ procedure periodically to check whether all APs have finished.
+
+ @param[in] Event - Event triggered.
+ @param[in] Context - Parameter passed with the event.
+**/
+VOID
+CheckAllAPsStatus (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ UINTN CpuNumber;
+ UINTN NextCpuNumber;
+ CPU_DATA_BLOCK *CpuData;
+ CPU_DATA_BLOCK *NextCpuData;
+ EFI_STATUS Status;
+ CPU_STATE CpuState;
+
+ for (CpuNumber = 0; CpuNumber < mMPSystemData->NumberOfCpus; CpuNumber++) {
+ CpuData = &mMPSystemData->CpuData[CpuNumber];
+ if (CpuNumber == mMPSystemData->BSP) {
+ continue;
+ }
+
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuState = CpuData->State;
+ AsmReleaseMPLock (&CpuData->StateLock);
+
+ switch (CpuState) {
+ case CPU_STATE_READY:
+ WakeUpAp (
+ CpuData,
+ mMPSystemData->Procedure,
+ mMPSystemData->ProcArguments
+ );
+ break;
+
+ case CPU_STATE_FINISHED:
+ if (mMPSystemData->SingleThread) {
+ Status = GetNextBlockedCpuNumber (&NextCpuNumber);
+ if (!EFI_ERROR (Status)) {
+ NextCpuData = &mMPSystemData->CpuData[NextCpuNumber];
+
+ AsmAcquireMPLock (&NextCpuData->StateLock);
+ NextCpuData->State = CPU_STATE_READY;
+ AsmReleaseMPLock (&NextCpuData->StateLock);
+
+ WakeUpAp (
+ NextCpuData,
+ mMPSystemData->Procedure,
+ mMPSystemData->ProcArguments
+ );
+ }
+ }
+
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuData->State = CPU_STATE_IDLE;
+ AsmReleaseMPLock (&CpuData->StateLock);
+
+ mMPSystemData->FinishCount++;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (mMPSystemData->FinishCount == mMPSystemData->StartCount) {
+ gBS->SetTimer (
+ mMPSystemData->CheckAllAPsEvent,
+ TimerCancel,
+ 0
+ );
+ Status = gBS->SignalEvent (mMPSystemData->WaitEvent);
+ }
+
+ return;
+}
+
+/**
+ Check if this AP has finished task
+
+ @param[in] Event - Event triggered.
+ @param[in] Context - Parameter passed with the event.
+**/
+VOID
+CheckThisAPStatus (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ CPU_DATA_BLOCK *CpuData;
+ EFI_STATUS Status;
+ CPU_STATE CpuState;
+
+ CpuData = (CPU_DATA_BLOCK *) Context;
+
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuState = CpuData->State;
+ AsmReleaseMPLock (&CpuData->StateLock);
+
+ if (CpuState == CPU_STATE_FINISHED) {
+ gBS->SetTimer (
+ CpuData->CheckThisAPEvent,
+ TimerCancel,
+ 0
+ );
+ Status = gBS->SignalEvent (mMPSystemData->WaitEvent);
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuData->State = CPU_STATE_IDLE;
+ AsmReleaseMPLock (&CpuData->StateLock);
+ }
+
+ return;
+}
+
+/**
+ Convert the timeout value to TSC value
+
+ @param[in] TimeoutInMicroSecs - how many microseconds the timeout is
+
+ @retval expected TSC value for timeout
+**/
+UINT64
+CalculateTimeout (
+ IN UINTN TimeoutInMicroSecs
+ )
+{
+ UINT64 CurrentTsc;
+ UINT64 ExpectedTsc;
+ UINT64 Frequency;
+ EFI_STATUS Status;
+
+ if (TimeoutInMicroSecs == 0) {
+ return 0xffffffffffff;
+ }
+
+ CurrentTsc = EfiReadTsc ();
+
+ Status = GetActualFrequency (mMetronome, &Frequency);
+
+ ExpectedTsc = CurrentTsc + MultU64x32 (Frequency, (UINT32) TimeoutInMicroSecs);
+
+ return ExpectedTsc;
+}
+
+/**
+ Check if timeout happened
+
+ @param[in] ExpectedTsc - the TSC value for timeout
+
+ @retval TRUE if timeout happened
+ @retval FALSE if timeout not yet happened
+**/
+BOOLEAN
+CheckTimeout (
+ IN UINT64 ExpectedTsc
+ )
+{
+ UINT64 CurrentTsc;
+
+ CurrentTsc = EfiReadTsc ();
+ if (CurrentTsc >= ExpectedTsc) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Get the next blocked processor
+
+ @param[in] NextCpuNumber - that will be updated for next blocked CPU number
+
+ @retval EFI_SUCCESS - The next blocked CPU found
+ @retval EFI_NOT_FOUND - cannot find blocked CPU
+**/
+EFI_STATUS
+GetNextBlockedCpuNumber (
+ OUT UINTN *NextCpuNumber
+ )
+{
+ UINTN CpuNumber;
+ CPU_STATE CpuState;
+ CPU_DATA_BLOCK *CpuData;
+
+ for (CpuNumber = 0; CpuNumber < mMPSystemData->NumberOfCpus; CpuNumber++) {
+ if (CpuNumber == mMPSystemData->BSP) {
+ continue;
+ }
+
+ CpuData = &mMPSystemData->CpuData[CpuNumber];
+
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuState = CpuData->State;
+ AsmReleaseMPLock (&CpuData->StateLock);
+
+ if (CpuState == CPU_STATE_BLOCKED) {
+ *NextCpuNumber = CpuNumber;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Update data hub for processor status
+
+ @param[in] CpuNumber - CPU number
+ @param[in] CpuDataforDatahub - the data hub that will be updated
+**/
+VOID
+UpdateDataforDatahub (
+ IN UINTN CpuNumber,
+ OUT CPU_DATA_FOR_DATAHUB *CpuDataforDatahub
+ )
+{
+ CpuDataforDatahub->Status = GetProcessorStatus (CpuNumber);
+ InitializeProcessorData (CpuNumber, CpuDataforDatahub);
+ InitializeCacheData (CpuNumber, CpuDataforDatahub->CacheInformation);
+
+ return;
+}
+
+/**
+ Function to wake up a specified AP and assign procedure to it.
+
+ @param[in] CpuData - CPU data block for the specified AP.
+ @param[in] Procedure - Procedure to assign.
+ @param[in] ProcArguments - Argument for Procedure.
+**/
+VOID
+WakeUpAp (
+ IN CPU_DATA_BLOCK *CpuData,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN VOID *ProcArguments
+ )
+{
+ MP_CPU_EXCHANGE_INFO *ExchangeInfo;
+ MONITOR_MWAIT_DATA *MonitorAddr;
+
+ AsmAcquireMPLock (&CpuData->ProcedureLock);
+ CpuData->Parameter = ProcArguments;
+ CpuData->Procedure = Procedure;
+ AsmReleaseMPLock (&CpuData->ProcedureLock);
+
+ ExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (mAcpiCpuData->WakeUpBuffer + MP_CPU_EXCHANGE_INFO_OFFSET);
+ MonitorAddr = (MONITOR_MWAIT_DATA *)
+ (
+ (UINT8 *) ExchangeInfo->StackStart +
+ (ExchangeInfo->BistBuffer[CpuData->ApicID].Number + 1) *
+ ExchangeInfo->StackSize -
+ MONITOR_FILTER_SIZE
+ );
+
+ if (MonitorAddr->WakeUpApVectorChangeFlag == TRUE || ExchangeInfo->WakeUpApManner == WakeUpApPerHltLoop) {
+ SendInterrupt (
+ BROADCAST_MODE_SPECIFY_CPU,
+ CpuData->ApicID,
+ 0,
+ DELIVERY_MODE_INIT,
+ TRIGGER_MODE_EDGE,
+ TRUE
+ );
+ SendInterrupt (
+ BROADCAST_MODE_SPECIFY_CPU,
+ CpuData->ApicID,
+ (UINT32) RShiftU64 (mAcpiCpuData->WakeUpBuffer,
+ 12),
+ DELIVERY_MODE_SIPI,
+ TRIGGER_MODE_EDGE,
+ TRUE
+ );
+ MonitorAddr->WakeUpApVectorChangeFlag = FALSE;
+
+ //
+ // Clear StateLock to 0 to avoid AP locking it then entering SMM and getting INIT-SIPI here could cause dead-lock
+ //
+ CpuData->StateLock = 0;
+ }
+
+ MonitorAddr->BreakToRunApSignal = (UINTN) (BREAK_TO_RUN_AP_SIGNAL | CpuData->ApicID);
+}
+
+/**
+ Check whether any AP is running for assigned task.
+
+ @retval TRUE - Some APs are running.
+ @retval FALSE - No AP is running.
+**/
+BOOLEAN
+ApRunning (
+ VOID
+ )
+{
+ CPU_DATA_BLOCK *CpuData;
+ UINTN CpuNumber;
+
+ for (CpuNumber = 0; CpuNumber < mMPSystemData->NumberOfCpus; CpuNumber++) {
+ CpuData = &mMPSystemData->CpuData[CpuNumber];
+
+ if (CpuNumber != mMPSystemData->BSP) {
+ if (CpuData->State == CPU_STATE_READY || CpuData->State == CPU_STATE_BUSY) {
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ Re-load microcode patch before boot.
+
+ @param[in] MpServices - point to EFI_MP_SERVICES_PROTOCOL
+
+ @retval EFI_SUCCESS - one processor re-loads microcode patch
+**/
+EFI_STATUS
+ReLoadMicrocodePatch (
+ IN EFI_MP_SERVICES_PROTOCOL *MpServices
+ )
+{
+ UINT32 FailedRevision;
+ UINTN CpuNumber;
+ EFI_STATUS Status;
+
+ Status = InitializeMicrocode (
+ mMicrocodePointerBuffer,
+ &FailedRevision
+ );
+ WhoAmI (
+ &mMpService,
+ &CpuNumber
+ );
+ Status = CheckMicrocodeUpdate (
+ CpuNumber,
+ Status,
+ FailedRevision
+ );
+ return Status;
+}
+
+/**
+ Re-load microcode patch before boot.
+
+ @retval EFI_SUCCESS - Multiple processors re-load microcode patch
+**/
+EFI_STATUS
+ReLoadMicrocodeBeforeBoot (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ ///
+ /// Added code to handle microcode patch reload here!!!
+ ///
+ mMcuLoadCount = 0;
+ Status = ReLoadMicrocodePatch (&mMpService);
+ if (!EFI_ERROR (Status)) {
+ Status = mMpService.StartupAllAPs (
+ &mMpService,
+ ReLoadMicrocodePatch,
+ FALSE,
+ NULL,
+ 0,
+ (VOID *) &mMpService,
+ NULL
+ );
+ }
+ return Status;
+}
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/MpService.h b/ReferenceCode/Haswell/CpuInit/Dxe/MpService.h
new file mode 100644
index 0000000..7fa7544
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/MpService.h
@@ -0,0 +1,670 @@
+/** @file
+ Some definitions for MP services Protocol.
+
+@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 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
+
+**/
+#ifndef _MP_SERVICE_H_
+#define _MP_SERVICE_H_
+
+#include "MpCommon.h"
+
+///
+/// Driver Produced Protocol.
+///
+#include EFI_PROTOCOL_PRODUCER (MpService)
+#include EFI_PROTOCOL_PRODUCER (PiMpService)
+
+//
+// Constant definitions
+//
+#define FOURGB 0x100000000
+#define ONEPAGE 0x1000
+
+#define RENDEZVOUS_PROC_LENGTH 0x1000
+#define STACK_SIZE_PER_PROC 0x8000
+#define MAX_CPU_S3_MTRR_ENTRY 0x0020
+#define MAX_CPU_S3_TABLE_SIZE 0x0400
+
+#define AP_HALT_CODE_SIZE 10
+
+#define CPU_CHECK_AP_INTERVAL 10 // multiply to microseconds for gBS->SetTimer in 100nsec.
+#define CPU_WAIT_FOR_TASK_TO_BE_COMPLETED 100000 // microseconds
+///
+/// The MP data structure follows.
+///
+#define CPU_SWITCH_STATE_IDLE 0
+#define CPU_SWITCH_STATE_STORED 1
+#define CPU_SWITCH_STATE_LOADED 2
+
+#define MSR_L3_CACHE_DISABLE 0x40
+
+typedef struct {
+ UINT8 Lock; ///< offset 0
+ UINT8 State; ///< offset 1
+ UINTN StackPointer; ///< offset 4 / 8
+ PSEUDO_DESCRIPTOR Gdtr; ///< offset 8 / 16
+ PSEUDO_DESCRIPTOR Idtr; ///< offset 14 / 26
+} CPU_EXCHANGE_ROLE_INFO;
+
+//
+// MTRR table definitions
+//
+typedef struct {
+ UINT16 Index;
+ UINT64 Value;
+} EFI_MTRR_VALUES;
+
+typedef enum {
+ CPU_STATE_IDLE,
+ CPU_STATE_BLOCKED,
+ CPU_STATE_READY,
+ CPU_STATE_BUSY,
+ CPU_STATE_FINISHED,
+ CPU_STATE_DISABLED
+} CPU_STATE;
+
+//
+// Define CPU feature information
+//
+#define MAX_FEATURE_NUM 6
+typedef struct {
+ UINTN Index;
+ UINT32 ApicId;
+ UINT32 Version;
+ UINT32 FeatureDelta;
+ UINT32 Features[MAX_FEATURE_NUM];
+} LEAST_FEATURE_PROC;
+
+///
+/// Define Individual Processor Data block.
+///
+typedef struct {
+ UINT32 ApicID;
+ EFI_AP_PROCEDURE Procedure;
+ VOID *Parameter;
+ UINT8 StateLock;
+ UINT8 ProcedureLock;
+ EFI_MP_HEALTH_FLAGS Health;
+ BOOLEAN SecondaryCpu;
+ UINTN NumberOfCores;
+ UINTN NumberOfThreads;
+ UINT64 ActualFsbFrequency;
+ EFI_STATUS MicrocodeStatus;
+ UINT32 FailedRevision;
+ PHYSICAL_LOCATION PhysicalLocation;
+ CPU_STATE State;
+ CPU_DATA_FOR_DATAHUB CpuDataforDatahub;
+
+ //
+ // for PI MP Services Protocol
+ //
+ BOOLEAN *Finished;
+ UINT64 ExpectedTime;
+ EFI_EVENT WaitEvent;
+ EFI_EVENT CheckThisAPEvent;
+} CPU_DATA_BLOCK;
+
+typedef struct {
+ UINT32 ApicId;
+ UINT32 MsrIndex;
+ UINT64 MsrValue;
+} MP_CPU_S3_SCRIPT_DATA;
+
+typedef struct {
+ UINT32 S3BootScriptTable;
+ UINT32 S3BspMtrrTable;
+} MP_CPU_S3_DATA_POINTER;
+
+#pragma pack(1)
+typedef struct {
+ UINT32 ApicId;
+ EFI_MP_HEALTH_FLAGS Health;
+} BIST_HOB_DATA;
+#pragma pack()
+
+///
+/// Define MP data block which consumes individual processor block.
+///
+typedef struct {
+ UINT8 APSerializeLock;
+
+ BOOLEAN LimitCpuidMaximumValue; ///< make processor look like < F40
+ BOOLEAN VmxEnable;
+ BOOLEAN ProcessorVmxEnable;
+ BOOLEAN ProcessorBistEnable;
+ BOOLEAN TxtEnable;
+ BOOLEAN MonitorMwaitEnable;
+ BOOLEAN ExecuteDisableBit;
+ BOOLEAN MachineCheckEnable;
+ BOOLEAN XapicEnable;
+ BOOLEAN AesEnable;
+ BOOLEAN DebugInterfaceEnable;
+ BOOLEAN DebugInterfaceLockEnable;
+ BOOLEAN EnableSecondaryCpu;
+ UINTN NumberOfCpus;
+ UINTN MaximumCpusForThisSystem;
+
+ CPU_EXCHANGE_ROLE_INFO BSPInfo;
+ CPU_EXCHANGE_ROLE_INFO APInfo;
+
+ EFI_CPU_ARCH_PROTOCOL *CpuArch;
+ EFI_EVENT CheckAllAPsEvent;
+ EFI_EVENT WaitEvent;
+ UINTN BSP;
+ BIST_HOB_DATA *BistHobData;
+ UINTN BistHobSize;
+
+ UINTN FinishCount;
+ UINTN StartCount;
+ EFI_AP_PROCEDURE Procedure;
+ VOID *ProcArguments;
+ BOOLEAN SingleThread;
+ UINTN StartedCpuNumber;
+
+ CPU_DATA_BLOCK CpuData[MAXIMUM_CPU_NUMBER];
+ CPU_STATE_CHANGE_CAUSE DisableCause[MAXIMUM_CPU_NUMBER];
+
+ UINT8 S3BootScriptLock;
+ UINT32 S3BootScriptCount;
+ MP_CPU_S3_DATA_POINTER S3DataPointer;
+ MP_CPU_S3_SCRIPT_DATA S3BootScriptTable[MAX_CPU_S3_TABLE_SIZE];
+ EFI_MTRR_VALUES S3BspMtrrTable[MAX_CPU_S3_MTRR_ENTRY];
+
+ ///
+ /// for PI MP Services Protocol
+ ///
+ BOOLEAN CpuList[MAXIMUM_CPU_NUMBER];
+ UINTN **FailedCpuList;
+ UINT64 ExpectedTime;
+ EFI_EVENT CheckAPsEvent;
+} MP_SYSTEM_DATA;
+
+typedef struct {
+ ACPI_CPU_DATA AcpiCpuData;
+ MP_SYSTEM_DATA MPSystemData;
+ PSEUDO_DESCRIPTOR GdtrProfile;
+ PSEUDO_DESCRIPTOR IdtrProfile;
+ EFI_CPU_MICROCODE_HEADER *MicrocodePointerBuffer[NUMBER_OF_MICROCODE_UPDATE + 1];
+} MP_CPU_RESERVED_DATA;
+
+extern MP_SYSTEM_DATA *mMPSystemData;
+extern ACPI_CPU_DATA *mAcpiCpuData;
+extern EFI_MP_SERVICES_PROTOCOL mMpService;
+extern EFI_PI_MP_SERVICES_PROTOCOL mPiMpService;
+
+///
+/// Prototypes.
+///
+
+/**
+ Get general MP information
+
+ @param[in] This - EFI_MP_SERVICE_PROTOCOL
+ @param[in] NumberOfCPUs - Number of processors
+ @param[in] MaxiumNumberOfCPUs - Max supported number of processors
+ @param[in] NumberOfEnabledCPUs - Number of processors enabled
+ @param[in] RendezvousIntNumber - number of Rendezvous procedure
+ @param[in] RendezvousProcLength - length of Rendezvous procedure
+
+ @retval EFI_SUCCESS - always return success
+**/
+EFI_STATUS
+EFIAPI
+GetGeneralMPInfo (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ OUT UINTN *NumberOfCPUs,
+ OUT UINTN *MaxiumNumberOfCPUs,
+ OUT UINTN *NumberOfEnabledCPUs,
+ OUT UINTN *RendezvousIntNumber,
+ OUT UINTN *RendezvousProcLength
+ );
+
+/**
+ Get processor context
+
+ @param[in] This - EFI_MP_SERVICE_PROTOCOL
+ @param[in] ProcessorNumber - The handle number of processor.
+ @param[in] BufferLength - buffer length
+ @param[in] ProcessorContextBuffer - pointer to the buffer that will be updated
+
+ @retval EFI_INVALID_PARAMETER - buffer is NULL or CpuNumber our of range
+ @retval EFI_BUFFER_TOO_SMALL - buffer too small
+ @retval EFI_SUCCESS - got processor context successfully
+**/
+EFI_STATUS
+EFIAPI
+GetProcessorContext (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ IN OUT UINTN *BufferLength,
+ IN OUT EFI_MP_PROC_CONTEXT *ProcessorContextBuffer
+ );
+
+/**
+ MP Service to get specified application processor (AP)
+ to execute a caller-provided code stream.
+
+ @param[in] This - Pointer to MP Service Protocol
+ @param[in] Procedure - The procedure to be assigned to AP.
+ @param[in] ProcessorNumber - The handle number of processor.
+ @param[in] WaitEvent - If timeout, the event to be triggered after this AP finishes.
+ @param[in] TimeoutInMicroSecs - The timeout value in microsecond. Zero means infinity.
+ @param[in] ProcArguments - Argument for Procedure.
+
+ @retval EFI_INVALID_PARAMETER - Procudure is NULL.
+ @retval EFI_INVALID_PARAMETER - Number of CPU out of range, or it belongs to BSP.
+ @retval EFI_INVALID_PARAMETER - Specified CPU is not idle.
+ @retval EFI_SUCCESS - The AP has finished.
+ @retval EFI_TIMEOUT - Time goes out before the AP has finished.
+**/
+EFI_STATUS
+EFIAPI
+StartupThisAP (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN UINTN ProcessorNumber,
+ IN EFI_EVENT WaitEvent OPTIONAL,
+ IN UINTN TimeoutInMicroSecs OPTIONAL,
+ IN OUT VOID *ProcArguments OPTIONAL
+ );
+
+/**
+ MP Service to get all the available application processors (APs)
+ to execute a caller-provided code stream.
+
+ @param[in] This - Pointer to MP Service Protocol
+ @param[in] Procedure - The procedure to be assigned to APs.
+ @param[in] SingleThread - If true, all APs execute in block mode.
+ Otherwise, all APs exceute in non-block mode.
+ @param[in] WaitEvent - If timeout, the event to be triggered after all APs finish.
+ @param[in] TimeoutInMicroSecs - The timeout value in microsecond. Zero means infinity.
+ @param[in] ProcArguments - Argument for Procedure.
+ @param[in] FailedCPUList - If not NULL, all APs that fail to start will be recorded in the list.
+
+ @retval EFI_INVALID_PARAMETER - Procudure is NULL.
+ @retval EFI_SUCCESS - Only 1 logical processor exists.
+ @retval EFI_SUCCESS - All APs have finished.
+ @retval EFI_TIMEOUT - Time goes out before all APs have finished.
+**/
+EFI_STATUS
+EFIAPI
+StartupAllAPs (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN BOOLEAN SingleThread,
+ IN EFI_EVENT WaitEvent OPTIONAL,
+ IN UINTN TimeoutInMicroSecs OPTIONAL,
+ IN OUT VOID *ProcArguments OPTIONAL,
+ OUT UINTN *FailedCPUList OPTIONAL
+ );
+
+/**
+ MP Service to makes the current BSP into an AP and then switches the
+ designated AP into the AP. This procedure is usually called after a CPU
+ test that has found that BSP is not healthy to continue it's responsbilities.
+
+ @param[in] This - Pointer to MP Service Protocol.
+ @param[in] ProcessorNumber - The handle number of processor.
+ @param[in] EnableOldBSPState - Whether to enable or disable the original BSP.
+
+ @retval EFI_INVALID_PARAMETER - Number for Specified AP out of range.
+ @retval EFI_INVALID_PARAMETER - Number of specified CPU belongs to BSP.
+ @retval EFI_NOT_READY - Specified AP is not idle.
+ @retval EFI_SUCCESS - BSP successfully switched.
+**/
+EFI_STATUS
+EFIAPI
+SwitchBSP (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ IN BOOLEAN EnableOldBSPState
+ );
+
+/**
+ This procedure sends an IPI to the designated processor in
+ the requested delivery mode with the requested vector.
+
+ @param[in] This - Pointer to MP Service Protocol.
+ @param[in] ProcessorNumber - The handle number of processor.
+ @param[in] VectorNumber - Vector number.
+ @param[in] DeliveryMode - I/O APIC Interrupt Deliver Modes
+
+ @retval EFI_INVALID_PARAMETER - Input paramters were not correct.
+ @retval Other status - Status returned by SendInterrupt ()
+**/
+EFI_STATUS
+EFIAPI
+SendIPI (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ IN UINTN VectorNumber,
+ IN UINTN DeliveryMode
+ );
+
+/**
+ Implementation of EnableDisableAP() service of MP Services Protocol.
+
+ This service lets the caller enable or disable an AP.
+ This service may only be called from the BSP.
+
+ @param[in] This - A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] ProcessorNumber - The handle number of processor.
+ @param[in] NewAPState - Indicates whether the newstate of the AP is enabled or disabled.
+ @param[in] HealthState - Indicates new health state of the AP..
+
+ @retval EFI_SUCCESS - AP successfully enabled or disabled.
+ @retval EFI_DEVICE_ERROR - Caller processor is AP.
+ @retval EFI_NOT_FOUND - Processor with the handle specified by ProcessorNumber does not exist.
+ @retval EFI_INVALID_PARAMETERS - ProcessorNumber specifies the BSP.
+**/
+EFI_STATUS
+EFIAPI
+EnableDisableAP (
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ IN BOOLEAN NewAPState,
+ IN EFI_MP_HEALTH *HealthState OPTIONAL
+ );
+
+/**
+ Initialize multiple processors and collect MP related data
+
+ @retval EFI_SUCCESS - Multiple processors get initialized and data collected successfully
+ @retval Other - The operation failed due to some reason
+**/
+EFI_STATUS
+InitializeMpSystemData (
+ VOID
+ );
+
+/**
+ Wake up all the application processors
+
+ @param[in] ImageHandle - The firmware allocated handle for the EFI image.
+ @param[in] SystemTable - A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS - APs are successfully waked up
+**/
+EFI_STATUS
+WakeUpAPs (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Exchange 2 processors (BSP to AP or AP to BSP)
+
+ @param[in] MyInfo - CPU info for current processor
+ @param[in] OthersInfo - CPU info that will be exchanged with
+**/
+VOID
+AsmExchangeRole (
+ IN CPU_EXCHANGE_ROLE_INFO *MyInfo,
+ IN CPU_EXCHANGE_ROLE_INFO *OthersInfo
+ );
+
+/**
+ Switch current BSP processor to AP
+
+ @param[in] MPSystemData - Pointer to the data structure containing MP related data
+**/
+VOID
+FutureBSPProc (
+ IN MP_SYSTEM_DATA *MPSystemData
+ );
+
+/**
+ Searches the HOB list provided by the core to find
+ if a MP guided HOB list exists or not. If it does, it copies it to the driver
+ data area, else returns 0
+
+ @param[in] MPSystemData - Pointer to an MP_SYSTEM_DATA structure
+
+ @retval EFI_SUCCESS - Success
+ @retval EFI_NOT_FOUND - HOB not found or else
+**/
+EFI_STATUS
+GetMpBistStatus (
+ IN MP_SYSTEM_DATA *MPSystemData
+ );
+
+/**
+ Initialize the state information for the MP DXE Protocol.
+**/
+VOID
+EFIAPI
+InitializeMpServices (
+ VOID
+ );
+
+/**
+ Prepare for MTRR synchronization.
+
+ @retval CR4 value before changing.
+**/
+UINTN
+MpMtrrSynchUpEntry (
+ VOID
+ );
+
+/**
+ Restoration after MTRR synchronization.
+
+ @param[in] Cr4 - CR4 value before changing.
+**/
+VOID
+MpMtrrSynchUpExit (
+ UINTN Cr4
+ );
+
+/**
+ Copy Global MTRR data to S3
+**/
+VOID
+SaveBspMtrrForS3 (
+ VOID
+ );
+
+/**
+ This function is called by all processors (both BSP and AP) once and collects MP related data
+
+ @param[in] MPSystemData - Pointer to the data structure containing MP related data
+ @param[in] BSP - TRUE if the CPU is BSP
+ @param[in] BistParam - BIST (build-in self test) data for the processor. This data
+ is only valid for processors that are waked up for the 1st
+ time in this CPU DXE driver.
+
+ @retval EFI_SUCCESS - Data for the processor collected and filled in
+**/
+EFI_STATUS
+FillInProcessorInformation (
+ IN MP_SYSTEM_DATA *MPSystemData,
+ IN BOOLEAN BSP,
+ IN UINT32 BistParam
+ );
+
+/**
+ Set APIC BSP bit
+
+ @param[in] Enable - enable as BSP or not
+
+ @retval EFI_SUCCESS - always return success
+**/
+EFI_STATUS
+SetApicBSPBit (
+ IN BOOLEAN Enable
+ );
+
+/**
+ Switch BSP to the processor which has least features
+
+ @param[in] MpServices - EFI_MP_SERVICES_PROTOCOL
+
+ @retval EFI_STATUS - status code returned from each sub-routines
+**/
+EFI_STATUS
+SwitchToLowestFeatureProcess (
+ IN EFI_MP_SERVICES_PROTOCOL *MpServices
+ );
+
+/**
+ Change CPU state
+
+ @param[in] CpuNumber - CPU number
+ @param[in] NewState - the new state that will be changed to
+ @param[in] Cause - Cause
+
+ @retval EFI_SUCCESS - always return success
+**/
+EFI_STATUS
+ChangeCpuState (
+ IN UINTN CpuNumber,
+ IN BOOLEAN NewState,
+ IN CPU_STATE_CHANGE_CAUSE Cause
+ );
+
+/**
+ Check if this is non-core processor - HT AP thread
+
+ @retval TRUE if this is HT AP thread
+ @retval FALSE if this is core thread
+**/
+BOOLEAN
+IsSecondaryThread (
+ VOID
+ );
+
+/**
+ If timeout occurs in StartupAllAps(), a timer is set, which invokes this
+ procedure periodically to check whether all APs have finished.
+
+ @param[in] Event - Event triggered.
+ @param[in] Context - Parameter passed with the event.
+**/
+VOID
+CheckAllAPsStatus (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ Check if this AP has finished task
+
+ @param[in] Event - Event triggered.
+ @param[in] Context - Parameter passed with the event.
+**/
+VOID
+CheckThisAPStatus (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ Convert the timeout value to TSC value
+
+ @param[in] TimeoutInMicroSecs - how many microseconds the timeout is
+
+ @retval expected TSC value for timeout
+**/
+UINT64
+CalculateTimeout (
+ IN UINTN TimeoutInMicroSecs
+ );
+
+/**
+ Check if timeout happened
+
+ @param[in] ExpectedTsc - the TSC value for timeout
+
+ @retval TRUE if timeout happened
+ @retval FALSE if timeout not yet happened
+**/
+BOOLEAN
+CheckTimeout (
+ IN UINT64 ExpectedTsc
+ );
+
+/**
+ Get the next blocked processor
+
+ @param[in] NextCpuNumber - that will be updated for next blocked CPU number
+
+ @retval EFI_SUCCESS - The next blocked CPU found
+ @retval EFI_NOT_FOUND - cannot find blocked CPU
+**/
+EFI_STATUS
+GetNextBlockedCpuNumber (
+ OUT UINTN *NextCpuNumber
+ );
+
+/**
+ Update data hub for processor status
+
+ @param[in] CpuNumber - CPU number
+ @param[in] CpuDataforDatahub - the data hub that will be updated
+**/
+VOID
+UpdateDataforDatahub (
+ IN UINTN CpuNumber,
+ OUT CPU_DATA_FOR_DATAHUB *CpuDataforDatahub
+ );
+
+/**
+ Procedure for detailed initialization of APs. It will be assigned to all APs while
+ they are waken up for the second time.
+**/
+VOID
+DetailedMpInitialization (
+ VOID
+ );
+
+/**
+ Function to wake up a specified AP and assign procedure to it.
+
+ @param[in] CpuData - CPU data block for the specified AP.
+ @param[in] Procedure - Procedure to assign.
+ @param[in] Parameter - Argument for Procedure.
+**/
+VOID
+WakeUpAp (
+ IN CPU_DATA_BLOCK *CpuData,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN VOID *Parameter
+ );
+
+/**
+ Check number of cores in the package.
+
+ @retval Number of cores in the package.
+**/
+UINT8
+GetCoreNumber (
+ VOID
+ );
+
+/**
+ Re-load microcode patch before boot.
+
+ @retval EFI_SUCCESS - Multiple processors re-load microcode patch
+**/
+EFI_STATUS
+ReLoadMicrocodeBeforeBoot (
+ VOID
+ );
+
+#endif
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/MtrrSync.c b/ReferenceCode/Haswell/CpuInit/Dxe/MtrrSync.c
new file mode 100644
index 0000000..a696e6b
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/MtrrSync.c
@@ -0,0 +1,338 @@
+/** @file
+ Code which support multi-processor
+
+@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 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
+**/
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "MpService.h"
+#endif
+
+extern MP_SYSTEM_DATA *mMPSystemData;
+
+EFI_MTRR_VALUES mFixedMtrrValues[] = {
+ {
+ IA32_MTRR_FIX64K_00000,
+ 0
+ },
+ {
+ IA32_MTRR_FIX16K_80000,
+ 0
+ },
+ {
+ IA32_MTRR_FIX16K_A0000,
+ 0
+ },
+ {
+ IA32_MTRR_FIX4K_C0000,
+ 0
+ },
+ {
+ IA32_MTRR_FIX4K_C8000,
+ 0
+ },
+ {
+ IA32_MTRR_FIX4K_D0000,
+ 0
+ },
+ {
+ IA32_MTRR_FIX4K_D8000,
+ 0
+ },
+ {
+ IA32_MTRR_FIX4K_E0000,
+ 0
+ },
+ {
+ IA32_MTRR_FIX4K_E8000,
+ 0
+ },
+ {
+ IA32_MTRR_FIX4K_F0000,
+ 0
+ },
+ {
+ IA32_MTRR_FIX4K_F8000,
+ 0
+ }
+};
+
+EFI_MTRR_VALUES mMtrrDefType[] = { { CACHE_IA32_MTRR_DEF_TYPE, 0 } };
+
+///
+/// Pre-defined Variable MTRR number to 20
+///
+EFI_MTRR_VALUES mVariableMtrrValues[] = {
+ {
+ CACHE_VARIABLE_MTRR_BASE,
+ 0
+ },
+ {
+ CACHE_VARIABLE_MTRR_BASE + 1,
+ 0
+ },
+ {
+ CACHE_VARIABLE_MTRR_BASE + 2,
+ 0
+ },
+ {
+ CACHE_VARIABLE_MTRR_BASE + 3,
+ 0
+ },
+ {
+ CACHE_VARIABLE_MTRR_BASE + 4,
+ 0
+ },
+ {
+ CACHE_VARIABLE_MTRR_BASE + 5,
+ 0
+ },
+ {
+ CACHE_VARIABLE_MTRR_BASE + 6,
+ 0
+ },
+ {
+ CACHE_VARIABLE_MTRR_BASE + 7,
+ 0
+ },
+ {
+ CACHE_VARIABLE_MTRR_BASE + 8,
+ 0
+ },
+ {
+ CACHE_VARIABLE_MTRR_BASE + 9,
+ 0
+ },
+ {
+ CACHE_VARIABLE_MTRR_BASE + 10,
+ 0
+ },
+ {
+ CACHE_VARIABLE_MTRR_BASE + 11,
+ 0
+ },
+ {
+ CACHE_VARIABLE_MTRR_BASE + 12,
+ 0
+ },
+ {
+ CACHE_VARIABLE_MTRR_BASE + 13,
+ 0
+ },
+ {
+ CACHE_VARIABLE_MTRR_BASE + 14,
+ 0
+ },
+ {
+ CACHE_VARIABLE_MTRR_BASE + 15,
+ 0
+ },
+ {
+ CACHE_VARIABLE_MTRR_BASE + 16,
+ 0
+ },
+ {
+ CACHE_VARIABLE_MTRR_BASE + 17,
+ 0
+ },
+ {
+ CACHE_VARIABLE_MTRR_BASE + 18,
+ 0
+ },
+ {
+ CACHE_VARIABLE_MTRR_BASE + 19,
+ 0
+ }
+};
+
+/**
+ Save the MTRR registers to global variables
+**/
+VOID
+ReadMtrrRegisters (
+ VOID
+ )
+{
+
+ UINT32 Index;
+ UINT32 VariableMtrrLimit;
+
+ VariableMtrrLimit = (UINT32) (AsmReadMsr64 (IA32_MTRR_CAP) & B_IA32_MTRR_VARIABLE_SUPPORT);
+ ///
+ /// Only support MAXIMUM_VARIABLE_MTRR_NUMBER variable MTRR
+ ///
+ ASSERT (VariableMtrrLimit <= V_MAXIMUM_VARIABLE_MTRR_NUMBER);
+ if (VariableMtrrLimit > V_MAXIMUM_VARIABLE_MTRR_NUMBER) {
+ VariableMtrrLimit = V_MAXIMUM_VARIABLE_MTRR_NUMBER;
+ }
+ ///
+ /// Read Fixed Mtrrs
+ ///
+ for (Index = 0; Index < sizeof (mFixedMtrrValues) / sizeof (EFI_MTRR_VALUES); Index++) {
+ mFixedMtrrValues[Index].Value = AsmReadMsr64 (mFixedMtrrValues[Index].Index);
+ }
+ ///
+ /// Read def type Fixed Mtrrs
+ ///
+ mMtrrDefType[0].Value = AsmReadMsr64 (CACHE_IA32_MTRR_DEF_TYPE);
+
+ ///
+ /// Read Variable Mtrr
+ ///
+ for (Index = 0; Index < VariableMtrrLimit * 2; Index++) {
+ mVariableMtrrValues[Index].Value = AsmReadMsr64 (mVariableMtrrValues[Index].Index);
+ }
+
+ return;
+}
+
+/**
+ Synch up the MTRR values for all processors
+
+ @param[in] Buffer - Not used.
+**/
+VOID
+EFIAPI
+MpMtrrSynchUp (
+ IN VOID *Buffer
+ )
+{
+ UINT32 Index;
+ UINTN Cr4;
+ UINT64 MsrValue;
+ UINT64 ValidMtrrAddressMask;
+ EFI_CPUID_REGISTER FeatureInfo;
+ EFI_CPUID_REGISTER FunctionInfo;
+ UINT8 PhysicalAddressBits;
+ UINT32 VariableMtrrLimit;
+
+ VariableMtrrLimit = (UINT32) (AsmReadMsr64 (IA32_MTRR_CAP) & B_IA32_MTRR_VARIABLE_SUPPORT);
+ ///
+ /// Only support MAXIMUM_VARIABLE_MTRR_NUMBER variable MTRR
+ ///
+ ASSERT (VariableMtrrLimit <= V_MAXIMUM_VARIABLE_MTRR_NUMBER);
+ if (VariableMtrrLimit > V_MAXIMUM_VARIABLE_MTRR_NUMBER) {
+ VariableMtrrLimit = V_MAXIMUM_VARIABLE_MTRR_NUMBER;
+ }
+ ///
+ /// ASM code to setup processor register before synching up the MTRRs
+ ///
+ Cr4 = MpMtrrSynchUpEntry ();
+
+ ///
+ /// Get physical CPU MTRR width in case of difference from BSP
+ ///
+ AsmCpuid (
+ CPUID_EXTENDED_FUNCTION,
+ &FunctionInfo.RegEax,
+ &FunctionInfo.RegEbx,
+ &FunctionInfo.RegEcx,
+ &FunctionInfo.RegEdx
+ );
+ PhysicalAddressBits = 36;
+ if (FunctionInfo.RegEax >= CPUID_VIR_PHY_ADDRESS_SIZE) {
+ AsmCpuid (
+ CPUID_VIR_PHY_ADDRESS_SIZE,
+ &FeatureInfo.RegEax,
+ &FeatureInfo.RegEbx,
+ &FeatureInfo.RegEcx,
+ &FeatureInfo.RegEdx
+ );
+ PhysicalAddressBits = (UINT8) FeatureInfo.RegEax;
+ }
+
+ ValidMtrrAddressMask = ((((UINT64) 1) << PhysicalAddressBits) - 1) & 0xfffffffffffff000;
+
+ ///
+ /// Disable Fixed Mtrrs
+ ///
+ AsmWriteMsr64 (CACHE_IA32_MTRR_DEF_TYPE, mMtrrDefType[0].Value & 0xFFFFF7FF);
+
+ ///
+ /// Update Fixed Mtrrs
+ ///
+ for (Index = 0; Index < sizeof (mFixedMtrrValues) / sizeof (EFI_MTRR_VALUES); Index++) {
+ AsmWriteMsr64 (mFixedMtrrValues[Index].Index, mFixedMtrrValues[Index].Value);
+ }
+ ///
+ /// Synchup def type Fixed Mtrrs
+ ///
+ AsmWriteMsr64 (CACHE_IA32_MTRR_DEF_TYPE, mMtrrDefType[0].Value);
+
+ ///
+ /// Synchup Base Variable Mtrr
+ ///
+ for (Index = 0; Index < VariableMtrrLimit * 2 - 1; Index += 2) {
+ MsrValue = (mVariableMtrrValues[Index].Value & 0x0FFF) | (mVariableMtrrValues[Index].Value & ValidMtrrAddressMask);
+ AsmWriteMsr64 (mVariableMtrrValues[Index].Index, MsrValue);
+ }
+ ///
+ /// Synchup Mask Variable Mtrr including valid bit
+ ///
+ for (Index = 1; Index < VariableMtrrLimit * 2; Index += 2) {
+ MsrValue = (mVariableMtrrValues[Index].Value & 0x0FFF) | (mVariableMtrrValues[Index].Value & ValidMtrrAddressMask);
+ AsmWriteMsr64 (mVariableMtrrValues[Index].Index, MsrValue);
+ }
+ ///
+ /// ASM code to setup processor register after synching up the MTRRs
+ ///
+ MpMtrrSynchUpExit (Cr4);
+
+ return;
+}
+
+/**
+ Copy Global MTRR data to S3
+**/
+VOID
+SaveBspMtrrForS3 (
+ VOID
+ )
+{
+ UINTN Index;
+ UINTN TableIndex;
+ UINT32 VariableMtrrLimit;
+
+ VariableMtrrLimit = (UINT32) (AsmReadMsr64 (IA32_MTRR_CAP) & B_IA32_MTRR_VARIABLE_SUPPORT);
+ ///
+ /// Only support MAXIMUM_VARIABLE_MTRR_NUMBER variable MTRR
+ ///
+ ASSERT (VariableMtrrLimit <= V_MAXIMUM_VARIABLE_MTRR_NUMBER);
+ if (VariableMtrrLimit > V_MAXIMUM_VARIABLE_MTRR_NUMBER) {
+ VariableMtrrLimit = V_MAXIMUM_VARIABLE_MTRR_NUMBER;
+ }
+
+ TableIndex = 0;
+ for (Index = 0; Index < sizeof (mFixedMtrrValues) / sizeof (EFI_MTRR_VALUES); Index++) {
+ mMPSystemData->S3BspMtrrTable[TableIndex].Index = mFixedMtrrValues[Index].Index;
+ mMPSystemData->S3BspMtrrTable[TableIndex].Value = mFixedMtrrValues[Index].Value;
+ TableIndex++;
+ }
+
+ for (Index = 0; Index < VariableMtrrLimit * 2; Index++) {
+ mMPSystemData->S3BspMtrrTable[TableIndex].Index = mVariableMtrrValues[Index].Index;
+ mMPSystemData->S3BspMtrrTable[TableIndex].Value = mVariableMtrrValues[Index].Value;
+ TableIndex++;
+ }
+
+ mMPSystemData->S3BspMtrrTable[TableIndex].Index = CACHE_IA32_MTRR_DEF_TYPE;
+ mMPSystemData->S3BspMtrrTable[TableIndex].Value = mMtrrDefType[0].Value;
+
+ ASSERT (TableIndex < MAX_CPU_S3_MTRR_ENTRY);
+
+ return;
+}
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/PiMpService.c b/ReferenceCode/Haswell/CpuInit/Dxe/PiMpService.c
new file mode 100644
index 0000000..a285f65
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/PiMpService.c
@@ -0,0 +1,957 @@
+/** @file
+ Implementation of PI MP Services Protocol
+
+@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 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
+
+@par Revision Reference:
+ - PI Version 1.2
+
+**/
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "PiMpService.h"
+#endif
+
+EFI_PI_MP_SERVICES_PROTOCOL mPiMpService = {
+ GetNumberOfProcessors,
+ GetProcessorInfo,
+ PiStartupAllAPs,
+ PiStartupThisAP,
+ PiSwitchBSP,
+ PiEnableDisableAP,
+ PiWhoAmI
+};
+
+BOOLEAN mStopCheckAPsStatus = FALSE;
+
+/**
+ Abort any task on the AP and reset the AP to be in idle state.
+
+ @param[in] ProcessorNumber - Processor index of an AP.
+**/
+VOID
+ResetProcessorToIdleState (
+ UINTN ProcessorNumber
+ )
+{
+ CPU_DATA_BLOCK *CpuData;
+
+ CpuData = &mMPSystemData->CpuData[ProcessorNumber];
+
+ SendIPI (
+ &mMpService,
+ ProcessorNumber,
+ 0,
+ DELIVERY_MODE_INIT
+ );
+
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuData->State = CPU_STATE_IDLE;
+ AsmReleaseMPLock (&CpuData->StateLock);
+}
+
+/**
+ Searches for the next waiting AP.
+
+ Search for the next AP that is put in waiting state by single-threaded StartupAllAPs().
+
+ @param[in] NextProcessorNumber - Pointer to the processor number of the next waiting AP.
+
+ @retval EFI_SUCCESS - The next waiting AP has been found.
+ @retval EFI_NOT_FOUND - No waiting AP exists.
+**/
+EFI_STATUS
+GetNextWaitingProcessorNumber (
+ OUT UINTN *NextProcessorNumber
+ )
+{
+ UINTN ProcessorNumber;
+
+ for (ProcessorNumber = 0; ProcessorNumber < mMPSystemData->NumberOfCpus; ProcessorNumber++) {
+
+ if (mMPSystemData->CpuList[ProcessorNumber]) {
+ *NextProcessorNumber = ProcessorNumber;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Checks status of all APs.
+
+ This function checks whether all APs have finished task assigned by StartupAllAPs(),
+ and whether timeout expires.
+
+ @retval EFI_SUCCESS - All APs have finished task assigned by StartupAllAPs().
+ @retval EFI_TIMEOUT - The timeout expires.
+ @retval EFI_NOT_READY - APs have not finished task and timeout has not expired.
+**/
+EFI_STATUS
+CheckAllAPs (
+ VOID
+ )
+{
+ UINTN ProcessorNumber;
+ UINTN NextProcessorNumber;
+ UINTN ListIndex;
+ EFI_STATUS Status;
+ CPU_STATE CpuState;
+ CPU_DATA_BLOCK *CpuData;
+
+ NextProcessorNumber = 0;
+
+ ///
+ /// Go through all APs that are responsible for the StartupAllAPs().
+ ///
+ for (ProcessorNumber = 0; ProcessorNumber < mMPSystemData->NumberOfCpus; ProcessorNumber++) {
+ if (!mMPSystemData->CpuList[ProcessorNumber]) {
+ continue;
+ }
+
+ CpuData = &mMPSystemData->CpuData[ProcessorNumber];
+
+ ///
+ /// Check the CPU state of AP. If it is CPU_STATE_FINISHED, then the AP has finished its task.
+ /// Only BSP and corresponding AP access this unit of CPU Data. This means the AP will not modify the
+ /// value of state after setting the it to CPU_STATE_FINISHED, so BSP can safely make use of its value.
+ ///
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuState = CpuData->State;
+ AsmReleaseMPLock (&CpuData->StateLock);
+
+ if (CpuState == CPU_STATE_FINISHED) {
+ mMPSystemData->FinishCount++;
+ mMPSystemData->CpuList[ProcessorNumber] = FALSE;
+
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuData->State = CPU_STATE_IDLE;
+ AsmReleaseMPLock (&CpuData->StateLock);
+
+ ///
+ /// If in Single Thread mode, then search for the next waiting AP for execution.
+ ///
+ if (mMPSystemData->SingleThread) {
+ Status = GetNextWaitingProcessorNumber (&NextProcessorNumber);
+
+ if (!EFI_ERROR (Status)) {
+ WakeUpAp (
+ &mMPSystemData->CpuData[NextProcessorNumber],
+ mMPSystemData->Procedure,
+ mMPSystemData->ProcArguments
+ );
+ }
+ }
+ }
+ }
+ ///
+ /// If all APs finish, return EFI_SUCCESS.
+ ///
+ if (mMPSystemData->FinishCount == mMPSystemData->StartCount) {
+ return EFI_SUCCESS;
+ }
+ ///
+ /// If timeout expires, report timeout.
+ ///
+ if (CheckTimeout (mMPSystemData->ExpectedTime)) {
+ ///
+ /// If FailedCpuList is not NULL, record all failed APs in it.
+ ///
+ if (mMPSystemData->FailedCpuList != NULL) {
+ Status = (gBS->AllocatePool)
+ (
+ EfiBootServicesData,
+ ((mMPSystemData->StartCount - mMPSystemData->FinishCount + 1) * sizeof (UINTN)),
+ (VOID **) mMPSystemData->FailedCpuList
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ ListIndex = 0;
+
+ for (ProcessorNumber = 0; ProcessorNumber < mMPSystemData->NumberOfCpus; ProcessorNumber++) {
+ ///
+ /// Check whether this processor is responsible for StartupAllAPs().
+ ///
+ if (mMPSystemData->CpuList[ProcessorNumber]) {
+ ///
+ /// Reset failed APs to idle state
+ ///
+ ResetProcessorToIdleState (ProcessorNumber);
+ mMPSystemData->CpuList[ProcessorNumber] = FALSE;
+ if (mMPSystemData->FailedCpuList != NULL) {
+ (*mMPSystemData->FailedCpuList)[ListIndex++] = ProcessorNumber;
+ }
+ }
+ }
+
+ if (mMPSystemData->FailedCpuList != NULL) {
+ (*mMPSystemData->FailedCpuList)[ListIndex] = END_OF_CPU_LIST;
+ }
+
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_NOT_READY;
+}
+
+/**
+ Checks status of specified AP.
+
+ This function checks whether specified AP has finished task assigned by StartupThisAP(),
+ and whether timeout expires.
+
+ @param[in] ProcessorNumber - The handle number of processor.
+
+ @retval EFI_SUCCESS - Specified AP has finished task assigned by StartupThisAPs().
+ @retval EFI_TIMEOUT - The timeout expires.
+ @retval EFI_NOT_READY - Specified AP has not finished task and timeout has not expired.
+**/
+EFI_STATUS
+CheckThisAP (
+ UINTN ProcessorNumber
+ )
+{
+ CPU_DATA_BLOCK *CpuData;
+ CPU_STATE CpuState;
+
+ CpuData = &mMPSystemData->CpuData[ProcessorNumber];
+
+ ///
+ /// Check the CPU state of AP. If it is CPU_STATE_FINISHED, then the AP has finished its task.
+ /// Only BSP and corresponding AP access this unit of CPU Data. This means the AP will not modify the
+ /// value of state after setting the it to CPU_STATE_FINISHED, so BSP can safely make use of its value.
+ ///
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuState = CpuData->State;
+ AsmReleaseMPLock (&CpuData->StateLock);
+
+ ///
+ /// If the APs finishes for StartupThisAP(), return EFI_SUCCESS.
+ ///
+ if (CpuState == CPU_STATE_FINISHED) {
+
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuData->State = CPU_STATE_IDLE;
+ AsmReleaseMPLock (&CpuData->StateLock);
+
+ if (CpuData->Finished != NULL) {
+ *(CpuData->Finished) = TRUE;
+ }
+
+ return EFI_SUCCESS;
+ } else {
+ ///
+ /// If timeout expires for StartupThisAP(), report timeout.
+ ///
+ if (CheckTimeout (CpuData->ExpectedTime)) {
+
+ if (CpuData->Finished != NULL) {
+ *(CpuData->Finished) = FALSE;
+ }
+ ///
+ /// Reset failed AP to idle state
+ ///
+ ResetProcessorToIdleState (ProcessorNumber);
+
+ return EFI_TIMEOUT;
+ }
+ }
+
+ return EFI_NOT_READY;
+}
+
+/**
+ Checks APs' status periodically.
+
+ This function is triggerred by timer perodically to check the
+ state of APs for StartupAllAPs() and StartupThisAP() executed
+ in non-blocking mode.
+
+ @param[in] Event - Event triggered.
+ @param[in] Context - Parameter passed with the event.
+**/
+VOID
+EFIAPI
+CheckAPsStatus (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ UINTN ProcessorNumber;
+ CPU_DATA_BLOCK *CpuData;
+ EFI_STATUS Status;
+
+ ///
+ /// If CheckAPsStatus() is stopped, then return immediately.
+ ///
+ if (mStopCheckAPsStatus) {
+ return;
+ }
+ ///
+ /// First, check whether pending StartupAllAPs() exists.
+ ///
+ if (mMPSystemData->WaitEvent != NULL) {
+
+ Status = CheckAllAPs ();
+ ///
+ /// If all APs finish for StartupAllAPs(), signal the WaitEvent for it..
+ ///
+ if (Status != EFI_NOT_READY) {
+ Status = gBS->SignalEvent (mMPSystemData->WaitEvent);
+ mMPSystemData->WaitEvent = NULL;
+ }
+ }
+ ///
+ /// Second, check whether pending StartupThisAPs() callings exist.
+ ///
+ for (ProcessorNumber = 0; ProcessorNumber < mMPSystemData->NumberOfCpus; ProcessorNumber++) {
+
+ CpuData = &mMPSystemData->CpuData[ProcessorNumber];
+
+ if (CpuData->WaitEvent == NULL) {
+ continue;
+ }
+
+ Status = CheckThisAP (ProcessorNumber);
+
+ if (Status != EFI_NOT_READY) {
+ gBS->SignalEvent (CpuData->WaitEvent);
+ CpuData->WaitEvent = NULL;
+ }
+ }
+
+ return;
+}
+
+/**
+ Implementation of GetNumberOfProcessors() service of MP Services Protocol.
+
+ This service retrieves the number of logical processor in the platform
+ and the number of those logical processors that are enabled on this boot.
+ This service may only be called from the BSP.
+
+ @param[in] This - A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] NumberOfProcessors - Pointer to the total number of logical processors in the system,
+ including the BSP and disabled APs.
+ @param[in] NumberOfEnabledProcessors - Pointer to the number of enabled logical processors that exist
+ in system, including the BSP.
+
+ @retval EFI_SUCCESS - Number of logical processors and enabled logical processors retrieved..
+ @retval EFI_DEVICE_ERROR - Caller processor is AP.
+ @retval EFI_INVALID_PARAMETER - NumberOfProcessors is NULL.
+ @retval EFI_INVALID_PARAMETER - NumberOfEnabledProcessors is NULL.
+**/
+EFI_STATUS
+EFIAPI
+GetNumberOfProcessors (
+ IN EFI_PI_MP_SERVICES_PROTOCOL *This,
+ OUT UINTN *NumberOfProcessors,
+ OUT UINTN *NumberOfEnabledProcessors
+ )
+{
+ EFI_STATUS Status;
+ UINTN CallerNumber;
+
+ ///
+ /// Check whether caller processor is BSP
+ ///
+ WhoAmI (&mMpService, &CallerNumber);
+ if (CallerNumber != mMPSystemData->BSP) {
+ return EFI_DEVICE_ERROR;
+ }
+ ///
+ /// Check parameter NumberOfProcessors and NumberOfEnabledProcessors
+ ///
+ if (NumberOfProcessors == NULL || NumberOfEnabledProcessors == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = GetGeneralMPInfo (
+ &mMpService,
+ NumberOfProcessors,
+ NULL,
+ NumberOfEnabledProcessors,
+ NULL,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/**
+ Implementation of GetNumberOfProcessors() service of MP Services Protocol.
+
+ Gets detailed MP-related information on the requested processor at the
+ instant this call is made. This service may only be called from the BSP.
+
+ @param[in] This - A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] ProcessorNumber - The handle number of processor.
+ @param[in] ProcessorInfoBuffer - A pointer to the buffer where information for the requested processor is deposited.
+
+ @retval EFI_SUCCESS - Processor information successfully returned.
+ @retval EFI_DEVICE_ERROR - Caller processor is AP.
+ @retval EFI_INVALID_PARAMETER - ProcessorInfoBuffer is NULL
+ @retval EFI_NOT_FOUND - Processor with the handle specified by ProcessorNumber does not exist.
+**/
+EFI_STATUS
+EFIAPI
+GetProcessorInfo (
+ IN EFI_PI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN CallerNumber;
+ UINTN BufferSize;
+ EFI_MP_PROC_CONTEXT ProcessorContextBuffer;
+
+ ///
+ /// Check whether caller processor is BSP
+ ///
+ WhoAmI (&mMpService, &CallerNumber);
+ if (CallerNumber != mMPSystemData->BSP) {
+ return EFI_DEVICE_ERROR;
+ }
+ ///
+ /// Check parameter ProcessorInfoBuffer
+ ///
+ if (ProcessorInfoBuffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ ///
+ /// Check whether processor with the handle specified by ProcessorNumber exists
+ ///
+ if (ProcessorNumber >= mMPSystemData->NumberOfCpus) {
+ return EFI_NOT_FOUND;
+ }
+
+ BufferSize = sizeof (EFI_MP_PROC_CONTEXT);
+ Status = GetProcessorContext (
+ &mMpService,
+ ProcessorNumber,
+ &BufferSize,
+ &ProcessorContextBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ProcessorInfoBuffer->ProcessorId = (UINT64) ProcessorContextBuffer.ApicID;
+
+ ///
+ /// Get Status Flag of specified processor
+ ///
+ ProcessorInfoBuffer->StatusFlag = 0;
+
+ if (ProcessorContextBuffer.Enabled) {
+ ProcessorInfoBuffer->StatusFlag |= PROCESSOR_ENABLED_BIT;
+ }
+
+ if (ProcessorContextBuffer.Designation == EfiCpuBSP) {
+ ProcessorInfoBuffer->StatusFlag |= PROCESSOR_AS_BSP_BIT;
+ }
+
+ if (ProcessorContextBuffer.Health.Flags.Uint32 == 0) {
+ ProcessorInfoBuffer->StatusFlag |= PROCESSOR_HEALTH_STATUS_BIT;
+ }
+
+ ProcessorInfoBuffer->Location.Package = (UINT32) ProcessorContextBuffer.PackageNumber;
+ ProcessorInfoBuffer->Location.Core = (UINT32) ProcessorContextBuffer.NumberOfCores;
+ ProcessorInfoBuffer->Location.Thread = (UINT32) ProcessorContextBuffer.NumberOfThreads;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Implementation of StartupAllAPs() service of MP Services Protocol.
+
+ This service lets the caller get all enabled APs to execute a caller-provided function.
+ This service may only be called from the BSP.
+
+ @param[in] This - A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] Procedure - A pointer to the function to be run on enabled APs of the system.
+ @param[in] SingleThread - Indicates whether to execute the function simultaneously or one by one..
+ @param[in] WaitEvent - The event created by the caller.
+ If it is NULL, then execute in blocking mode.
+ If it is not NULL, then execute in non-blocking mode.
+ @param[in] TimeoutInMicroSeconds - The time limit in microseconds for this AP to finish the function.
+ Zero means infinity.
+ @param[in] ProcedureArgument - Pointer to the optional parameter of the assigned function.
+ @param[in] FailedCpuList - The list of processor numbers that fail to finish the function before
+ TimeoutInMicrosecsond expires.
+
+ @retval EFI_SUCCESS - In blocking mode, all APs have finished before the timeout expired.
+ @retval EFI_SUCCESS - In non-blocking mode, function has been dispatched to all enabled APs.
+ @retval EFI_DEVICE_ERROR - Caller processor is AP.
+ @retval EFI_NOT_STARTED - No enabled AP exists in the system.
+ @retval EFI_NOT_READY - Any enabled AP is busy.
+ @retval EFI_TIMEOUT - In blocking mode, The timeout expired before all enabled APs have finished.
+ @retval EFI_INVALID_PARAMETER - Procedure is NULL.
+**/
+EFI_STATUS
+EFIAPI
+PiStartupAllAPs (
+ IN EFI_PI_MP_SERVICES_PROTOCOL *This,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN BOOLEAN SingleThread,
+ IN EFI_EVENT WaitEvent OPTIONAL,
+ IN UINTN TimeoutInMicroSeconds,
+ IN VOID *ProcedureArgument OPTIONAL,
+ OUT UINTN **FailedCpuList OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINTN ProcessorNumber;
+ CPU_DATA_BLOCK *CpuData;
+ BOOLEAN Blocking;
+
+ if (FailedCpuList != NULL) {
+ *FailedCpuList = NULL;
+ }
+ ///
+ /// Check whether caller processor is BSP
+ ///
+ WhoAmI (&mMpService, &ProcessorNumber);
+ if (ProcessorNumber != mMPSystemData->BSP) {
+ return EFI_DEVICE_ERROR;
+ }
+ ///
+ /// Check parameter Procedure
+ ///
+ if (Procedure == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ ///
+ /// Temporarily suppress CheckAPsStatus()
+ ///
+ mStopCheckAPsStatus = TRUE;
+
+ ///
+ /// Check whether all enabled APs are idle.
+ /// If any enabled AP is not idle, return EFI_NOT_READY.
+ ///
+ for (ProcessorNumber = 0; ProcessorNumber < mMPSystemData->NumberOfCpus; ProcessorNumber++) {
+
+ CpuData = &mMPSystemData->CpuData[ProcessorNumber];
+
+ mMPSystemData->CpuList[ProcessorNumber] = FALSE;
+ ///
+ /// Skip BSP and disabled APs.
+ ///
+ if (ProcessorNumber == mMPSystemData->BSP || CpuData->State == CPU_STATE_DISABLED) {
+ continue;
+ }
+ ///
+ /// If any enabled APs are busy, return EFI_NOT_FOUND.
+ ///
+ if (CpuData->State != CPU_STATE_IDLE) {
+ mStopCheckAPsStatus = FALSE;
+ return EFI_NOT_READY;
+ } else {
+ ///
+ /// Mark this processor as responsible for current calling.
+ ///
+ mMPSystemData->CpuList[ProcessorNumber] = TRUE;
+ }
+ }
+ ///
+ /// All enabled APs are idle, we can safely initiate a new session
+ ///
+ mMPSystemData->FinishCount = 0;
+ mMPSystemData->StartCount = 0;
+ Blocking = FALSE;
+ ///
+ /// Go through all enabled APs to wakeup them for Procedure.
+ /// If in Single Thread mode, then only one AP is woken up, and others are waiting.
+ ///
+ for (ProcessorNumber = 0; ProcessorNumber < mMPSystemData->NumberOfCpus; ProcessorNumber++) {
+
+ CpuData = &mMPSystemData->CpuData[ProcessorNumber];
+ ///
+ /// Check whether this processor is responsible for current calling.
+ ///
+ if (mMPSystemData->CpuList[ProcessorNumber]) {
+
+ mMPSystemData->StartCount++;
+
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuData->State = CPU_STATE_READY;
+ AsmReleaseMPLock (&CpuData->StateLock);
+
+ if (!Blocking) {
+ WakeUpAp (
+ CpuData,
+ Procedure,
+ ProcedureArgument
+ );
+ }
+
+ if (SingleThread) {
+ Blocking = TRUE;
+ }
+ }
+ }
+ ///
+ /// If no enabled AP exists, return EFI_NOT_STARTED.
+ ///
+ if (mMPSystemData->StartCount == 0) {
+ mStopCheckAPsStatus = FALSE;
+ return EFI_NOT_STARTED;
+ }
+ ///
+ /// If WaitEvent is not NULL, execute in non-blocking mode.
+ /// BSP saves data for CheckAPsStatus(), and returns EFI_SUCCESS.
+ /// CheckAPsStatus() will check completion and timeout periodically.
+ ///
+ mMPSystemData->Procedure = Procedure;
+ mMPSystemData->ProcArguments = ProcedureArgument;
+ mMPSystemData->SingleThread = SingleThread;
+ mMPSystemData->FailedCpuList = FailedCpuList;
+ mMPSystemData->ExpectedTime = CalculateTimeout (TimeoutInMicroSeconds);
+ mMPSystemData->WaitEvent = WaitEvent;
+
+ ///
+ /// Allow CheckAPsStatus()
+ ///
+ mStopCheckAPsStatus = FALSE;
+
+ if (WaitEvent != NULL) {
+ return EFI_SUCCESS;
+ }
+ ///
+ /// If WaitEvent is NULL, execute in blocking mode.
+ /// BSP checks APs'state until all APs finish or TimeoutInMicrosecsond expires.
+ ///
+ do {
+ Status = CheckAllAPs ();
+ } while (Status == EFI_NOT_READY);
+
+ return Status;
+}
+
+/**
+ Implementation of StartupThisAP() service of MP Services Protocol.
+
+ This service lets the caller get one enabled AP to execute a caller-provided function.
+ This service may only be called from the BSP.
+
+ @param[in] This - A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] Procedure - A pointer to the function to be run on the designated AP.
+ @param[in] ProcessorNumber - The handle number of AP..
+ @param[in] WaitEvent - The event created by the caller.
+ If it is NULL, then execute in blocking mode.
+ If it is not NULL, then execute in non-blocking mode.
+ @param[in] TimeoutInMicroseconds - The time limit in microseconds for this AP to finish the function.
+ Zero means infinity.
+ @param[in] ProcedureArgument - Pointer to the optional parameter of the assigned function.
+ @param[in] Finished - Indicates whether AP has finished assigned function.
+ In blocking mode, it is ignored.
+
+ @retval EFI_SUCCESS - In blocking mode, specified AP has finished before the timeout expires.
+ @retval EFI_SUCCESS - In non-blocking mode, function has been dispatched to specified AP.
+ @retval EFI_DEVICE_ERROR - Caller processor is AP.
+ @retval EFI_TIMEOUT - In blocking mode, the timeout expires before specified AP has finished.
+ @retval EFI_NOT_READY - Specified AP is busy.
+ @retval EFI_NOT_FOUND - Processor with the handle specified by ProcessorNumber does not exist.
+ @retval EFI_INVALID_PARAMETER - ProcessorNumber specifies the BSP or disabled AP.
+ @retval EFI_INVALID_PARAMETER - Procedure is NULL.
+**/
+EFI_STATUS
+EFIAPI
+PiStartupThisAP (
+ IN EFI_PI_MP_SERVICES_PROTOCOL *This,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN UINTN ProcessorNumber,
+ IN EFI_EVENT WaitEvent OPTIONAL,
+ IN UINTN TimeoutInMicroseconds,
+ IN VOID *ProcedureArgument OPTIONAL,
+ OUT BOOLEAN *Finished OPTIONAL
+ )
+{
+ CPU_DATA_BLOCK *CpuData;
+ UINTN CallerNumber;
+ EFI_STATUS Status;
+
+ if (Finished != NULL) {
+ *Finished = TRUE;
+ }
+ ///
+ /// Check whether caller processor is BSP
+ ///
+ WhoAmI (&mMpService, &CallerNumber);
+ if (CallerNumber != mMPSystemData->BSP) {
+ return EFI_DEVICE_ERROR;
+ }
+ ///
+ /// Check whether processor with the handle specified by ProcessorNumber exists
+ ///
+ if (ProcessorNumber >= mMPSystemData->NumberOfCpus) {
+ return EFI_NOT_FOUND;
+ }
+ ///
+ /// Check whether specified processor is BSP
+ ///
+ if (ProcessorNumber == mMPSystemData->BSP) {
+ return EFI_INVALID_PARAMETER;
+ }
+ ///
+ /// Check parameter Procedure
+ ///
+ if (Procedure == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CpuData = &mMPSystemData->CpuData[ProcessorNumber];
+
+ ///
+ /// Temporarily suppress CheckAPsStatus()
+ ///
+ mStopCheckAPsStatus = TRUE;
+
+ ///
+ /// Check whether specified AP is disabled
+ ///
+ if (CpuData->State == CPU_STATE_DISABLED) {
+ mStopCheckAPsStatus = FALSE;
+ return EFI_INVALID_PARAMETER;
+ }
+ ///
+ /// Check whether specified AP is busy
+ ///
+ if (CpuData->State != CPU_STATE_IDLE) {
+ mStopCheckAPsStatus = FALSE;
+ return EFI_NOT_READY;
+ }
+ ///
+ /// Wakeup specified AP for Procedure.
+ ///
+ AsmAcquireMPLock (&CpuData->StateLock);
+ CpuData->State = CPU_STATE_READY;
+ AsmReleaseMPLock (&CpuData->StateLock);
+
+ WakeUpAp (
+ CpuData,
+ Procedure,
+ ProcedureArgument
+ );
+
+ ///
+ /// If WaitEvent is not NULL, execute in non-blocking mode.
+ /// BSP saves data for CheckAPsStatus(), and returns EFI_SUCCESS.
+ /// CheckAPsStatus() will check completion and timeout periodically.
+ ///
+ CpuData->WaitEvent = WaitEvent;
+ CpuData->Finished = Finished;
+ CpuData->ExpectedTime = CalculateTimeout (TimeoutInMicroseconds);
+
+ ///
+ /// Allow CheckAPsStatus()
+ ///
+ mStopCheckAPsStatus = FALSE;
+
+ if (WaitEvent != NULL) {
+ return EFI_SUCCESS;
+ }
+ ///
+ /// If WaitEvent is NULL, execute in blocking mode.
+ /// BSP checks AP's state until it finishes or TimeoutInMicrosecsond expires.
+ ///
+ do {
+ Status = CheckThisAP (ProcessorNumber);
+ } while (Status == EFI_NOT_READY);
+
+ return Status;
+}
+
+/**
+ Implementation of SwitchBSP() service of MP Services Protocol.
+
+ This service switches the requested AP to be the BSP from that point onward.
+ This service may only be called from the current BSP.
+
+ @param[in] This - A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] ProcessorNumber - The handle number of processor.
+ @param[in] EnableOldBSP - Whether to enable or disable the original BSP.
+
+ @retval EFI_SUCCESS - BSP successfully switched.
+ @retval EFI_DEVICE_ERROR - Caller processor is AP.
+ @retval EFI_NOT_FOUND - Processor with the handle specified by ProcessorNumber does not exist.
+ @retval EFI_INVALID_PARAMETER - ProcessorNumber specifies the BSP or disabled AP.
+ @retval EFI_NOT_READY - Specified AP is busy.
+**/
+EFI_STATUS
+EFIAPI
+PiSwitchBSP (
+ IN EFI_PI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ IN BOOLEAN EnableOldBSP
+ )
+{
+ EFI_STATUS Status;
+ CPU_DATA_BLOCK *CpuData;
+ UINTN CallerNumber;
+
+ ///
+ /// Check whether caller processor is BSP
+ ///
+ WhoAmI (&mMpService, &CallerNumber);
+ if (CallerNumber != mMPSystemData->BSP) {
+ return EFI_DEVICE_ERROR;
+ }
+ ///
+ /// Check whether processor with the handle specified by ProcessorNumber exists
+ ///
+ if (ProcessorNumber >= mMPSystemData->NumberOfCpus) {
+ return EFI_NOT_FOUND;
+ }
+ ///
+ /// Check whether specified processor is BSP
+ ///
+ if (ProcessorNumber == mMPSystemData->BSP) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CpuData = &mMPSystemData->CpuData[ProcessorNumber];
+
+ ///
+ /// Check whether specified AP is disabled
+ ///
+ if (CpuData->State == CPU_STATE_DISABLED) {
+ return EFI_INVALID_PARAMETER;
+ }
+ ///
+ /// Check whether specified AP is busy
+ ///
+ if (CpuData->State != CPU_STATE_IDLE) {
+ return EFI_NOT_READY;
+ }
+
+ Status = SwitchBSP (
+ &mMpService,
+ ProcessorNumber,
+ EnableOldBSP
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ Implementation of EnableDisableAP() service of MP Services Protocol.
+
+ This service lets the caller enable or disable an AP.
+ This service may only be called from the BSP.
+
+ @param[in] This - A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] ProcessorNumber - The handle number of processor.
+ @param[in] EnableAP - Indicates whether the newstate of the AP is enabled or disabled.
+ @param[in] HealthFlag - Indicates new health state of the AP..
+
+ @retval EFI_SUCCESS - AP successfully enabled or disabled.
+ @retval EFI_DEVICE_ERROR - Caller processor is AP.
+ @retval EFI_NOT_FOUND - Processor with the handle specified by ProcessorNumber does not exist.
+ @retval EFI_INVALID_PARAMETERS - ProcessorNumber specifies the BSP.
+**/
+EFI_STATUS
+EFIAPI
+PiEnableDisableAP (
+ IN EFI_PI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ IN BOOLEAN EnableAP,
+ IN UINT32 *HealthFlag OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINTN CallerNumber;
+ EFI_MP_HEALTH HealthState;
+ EFI_MP_HEALTH *HealthStatePointer;
+
+ ///
+ /// Check whether caller processor is BSP
+ ///
+ WhoAmI (&mMpService, &CallerNumber);
+ if (CallerNumber != mMPSystemData->BSP) {
+ return EFI_DEVICE_ERROR;
+ }
+ ///
+ /// Check whether processor with the handle specified by ProcessorNumber exists
+ ///
+ if (ProcessorNumber >= mMPSystemData->NumberOfCpus) {
+ return EFI_NOT_FOUND;
+ }
+ ///
+ /// Check whether specified processor is BSP
+ ///
+ if (ProcessorNumber == mMPSystemData->BSP) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (HealthFlag == NULL) {
+ HealthStatePointer = NULL;
+ } else {
+ if ((*HealthFlag & PROCESSOR_HEALTH_STATUS_BIT) == 0) {
+ HealthState.Flags.Uint32 = 1;
+ } else {
+ HealthState.Flags.Uint32 = 0;
+ }
+
+ HealthState.TestStatus = 0;
+
+ HealthStatePointer = &HealthState;
+ }
+
+ Status = EnableDisableAP (
+ &mMpService,
+ ProcessorNumber,
+ EnableAP,
+ HealthStatePointer
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ Implementation of WhoAmI() service of MP Services Protocol.
+
+ This service lets the caller processor get its handle number.
+ This service may be called from the BSP and APs.
+
+ @param[in] This - A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] ProcessorNumber - Pointer to the handle number of AP.
+
+ @retval EFI_SUCCESS - Processor number successfully returned.
+ @retval EFI_INVALID_PARAMETER - ProcessorNumber is NULL
+**/
+EFI_STATUS
+EFIAPI
+PiWhoAmI (
+ IN EFI_PI_MP_SERVICES_PROTOCOL *This,
+ OUT UINTN *ProcessorNumber
+ )
+{
+ EFI_STATUS Status;
+
+ if (ProcessorNumber == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = WhoAmI (&mMpService, ProcessorNumber);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/PiMpService.h b/ReferenceCode/Haswell/CpuInit/Dxe/PiMpService.h
new file mode 100644
index 0000000..0e2bccf
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/PiMpService.h
@@ -0,0 +1,242 @@
+/** @file
+ some definitions for PI MP services Protocol.
+
+@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 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
+
+**/
+#ifndef _PI_MP_SERVICE_H_
+#define _PI_MP_SERVICE_H_
+
+#include "MpService.h"
+
+///
+/// Driver Produced Protocol.
+///
+#include EFI_PROTOCOL_PRODUCER (PiMpService)
+
+/**
+ Implementation of GetNumberOfProcessors() service of MP Services Protocol.
+
+ This service retrieves the number of logical processor in the platform
+ and the number of those logical processors that are enabled on this boot.
+ This service may only be called from the BSP.
+
+ @param[in] This - A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] NumberOfProcessors - Pointer to the total number of logical processors in the system,
+ including the BSP and disabled APs.
+ @param[in] NumberOfEnabledProcessors - Pointer to the number of enabled logical processors that exist
+ in system, including the BSP.
+
+ @retval EFI_SUCCESS - Number of logical processors and enabled logical processors retrieved..
+ @retval EFI_DEVICE_ERROR - Caller processor is AP.
+ @retval EFI_INVALID_PARAMETER - NumberOfProcessors is NULL.
+ @retval EFI_INVALID_PARAMETER - NumberOfEnabledProcessors is NULL.
+**/
+EFI_STATUS
+EFIAPI
+GetNumberOfProcessors (
+ IN EFI_PI_MP_SERVICES_PROTOCOL *This,
+ OUT UINTN *NumberOfProcessors,
+ OUT UINTN *NumberOfEnabledProcessors
+ );
+
+/**
+ Implementation of GetNumberOfProcessors() service of MP Services Protocol.
+
+ Gets detailed MP-related information on the requested processor at the
+ instant this call is made. This service may only be called from the BSP.
+
+ @param[in] This - A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] ProcessorNumber - The handle number of processor.
+ @param[in] ProcessorInfoBuffer - A pointer to the buffer where information for the requested processor is deposited.
+
+ @retval EFI_SUCCESS - Processor information successfully returned.
+ @retval EFI_DEVICE_ERROR - Caller processor is AP.
+ @retval EFI_INVALID_PARAMETER - ProcessorInfoBuffer is NULL
+ @retval EFI_NOT_FOUND - Processor with the handle specified by ProcessorNumber does not exist.
+**/
+EFI_STATUS
+EFIAPI
+GetProcessorInfo (
+ IN EFI_PI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
+ );
+
+/**
+ Implementation of StartupThisAP() service of MP Services Protocol.
+
+ This service lets the caller get one enabled AP to execute a caller-provided function.
+ This service may only be called from the BSP.
+
+ @param[in] This - A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] Procedure - A pointer to the function to be run on the designated AP.
+ @param[in] ProcessorNumber - The handle number of AP..
+ @param[in] WaitEvent - The event created by the caller.
+ If it is NULL, then execute in blocking mode.
+ If it is not NULL, then execute in non-blocking mode.
+ @param[in] TimeoutInMicroseconds - The time limit in microseconds for this AP to finish the function.
+ Zero means infinity.
+ @param[in] ProcedureArgument - Pointer to the optional parameter of the assigned function.
+ @param[in] Finished - Indicates whether AP has finished assigned function.
+ In blocking mode, it is ignored.
+
+ @retval EFI_SUCCESS - In blocking mode, specified AP has finished before the timeout expires.
+ @retval EFI_SUCCESS - In non-blocking mode, function has been dispatched to specified AP.
+ @retval EFI_DEVICE_ERROR - Caller processor is AP.
+ @retval EFI_TIMEOUT - In blocking mode, the timeout expires before specified AP has finished.
+ @retval EFI_NOT_READY - Specified AP is busy.
+ @retval EFI_NOT_FOUND - Processor with the handle specified by ProcessorNumber does not exist.
+ @retval EFI_INVALID_PARAMETER - ProcessorNumber specifies the BSP or disabled AP.
+ @retval EFI_INVALID_PARAMETER - Procedure is NULL.
+**/
+EFI_STATUS
+EFIAPI
+PiStartupThisAP (
+ IN EFI_PI_MP_SERVICES_PROTOCOL *This,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN UINTN ProcessorNumber,
+ IN EFI_EVENT WaitEvent OPTIONAL,
+ IN UINTN TimeoutInMicroseconds,
+ IN VOID *ProcedureArgument OPTIONAL,
+ OUT BOOLEAN *Finished OPTIONAL
+ );
+
+/**
+ Implementation of StartupAllAPs() service of MP Services Protocol.
+
+ This service lets the caller get all enabled APs to execute a caller-provided function.
+ This service may only be called from the BSP.
+
+ @param[in] This - A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] Procedure - A pointer to the function to be run on enabled APs of the system.
+ @param[in] SingleThread - Indicates whether to execute the function simultaneously or one by one..
+ @param[in] WaitEvent - The event created by the caller.
+ If it is NULL, then execute in blocking mode.
+ If it is not NULL, then execute in non-blocking mode.
+ @param[in] TimeoutInMicroSeconds - The time limit in microseconds for this AP to finish the function.
+ Zero means infinity.
+ @param[in] ProcedureArgument - Pointer to the optional parameter of the assigned function.
+ @param[in] FailedCpuList - The list of processor numbers that fail to finish the function before
+ TimeoutInMicrosecsond expires.
+
+ @retval EFI_SUCCESS - In blocking mode, all APs have finished before the timeout expired.
+ @retval EFI_SUCCESS - In non-blocking mode, function has been dispatched to all enabled APs.
+ @retval EFI_DEVICE_ERROR - Caller processor is AP.
+ @retval EFI_NOT_STARTED - No enabled AP exists in the system.
+ @retval EFI_NOT_READY - Any enabled AP is busy.
+ @retval EFI_TIMEOUT - In blocking mode, The timeout expired before all enabled APs have finished.
+ @retval EFI_INVALID_PARAMETER - Procedure is NULL.
+**/
+EFI_STATUS
+EFIAPI
+PiStartupAllAPs (
+ IN EFI_PI_MP_SERVICES_PROTOCOL *This,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN BOOLEAN SingleThread,
+ IN EFI_EVENT WaitEvent OPTIONAL,
+ IN UINTN TimeoutInMicroSeconds,
+ IN VOID *ProcedureArgument OPTIONAL,
+ OUT UINTN **FailedCpuList OPTIONAL
+ );
+
+/**
+ Implementation of SwitchBSP() service of MP Services Protocol.
+
+ This service switches the requested AP to be the BSP from that point onward.
+ This service may only be called from the current BSP.
+
+ @param[in] This - A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] ProcessorNumber - The handle number of processor.
+ @param[in] EnableOldBSP - Whether to enable or disable the original BSP.
+
+ @retval EFI_SUCCESS - BSP successfully switched.
+ @retval EFI_DEVICE_ERROR - Caller processor is AP.
+ @retval EFI_NOT_FOUND - Processor with the handle specified by ProcessorNumber does not exist.
+ @retval EFI_INVALID_PARAMETER - ProcessorNumber specifies the BSP or disabled AP.
+ @retval EFI_NOT_READY - Specified AP is busy.
+**/
+EFI_STATUS
+EFIAPI
+PiSwitchBSP (
+ IN EFI_PI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ IN BOOLEAN EnableOldBSP
+ );
+
+/**
+ Implementation of EnableDisableAP() service of MP Services Protocol.
+
+ This service lets the caller enable or disable an AP.
+ This service may only be called from the BSP.
+
+ @param[in] This - A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] ProcessorNumber - The handle number of processor.
+ @param[in] EnableAP - Indicates whether the newstate of the AP is enabled or disabled.
+ @param[in] HealthFlag - Indicates new health state of the AP..
+
+ @retval EFI_SUCCESS - AP successfully enabled or disabled.
+ @retval EFI_DEVICE_ERROR - Caller processor is AP.
+ @retval EFI_NOT_FOUND - Processor with the handle specified by ProcessorNumber does not exist.
+ @retval EFI_INVALID_PARAMETERS - ProcessorNumber specifies the BSP.
+**/
+EFI_STATUS
+EFIAPI
+PiEnableDisableAP (
+ IN EFI_PI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ IN BOOLEAN EnableAP,
+ IN UINT32 *HealthFlag OPTIONAL
+ );
+
+/**
+ Implementation of WhoAmI() service of MP Services Protocol.
+
+ This service lets the caller processor get its handle number.
+ This service may be called from the BSP and APs.
+
+ @param[in] This - A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] ProcessorNumber - Pointer to the handle number of AP.
+
+ @retval EFI_SUCCESS - Processor number successfully returned.
+ @retval EFI_INVALID_PARAMETER - ProcessorNumber is NULL
+**/
+EFI_STATUS
+EFIAPI
+PiWhoAmI (
+ IN EFI_PI_MP_SERVICES_PROTOCOL *This,
+ OUT UINTN *ProcessorNumber
+ );
+
+/**
+ Checks APs' status periodically.
+
+ This function is triggerred by timer perodically to check the
+ state of APs for StartupAllAPs() and StartupThisAP() executed
+ in non-blocking mode.
+
+ @param[in] Event - Event triggered.
+ @param[in] Context - Parameter passed with the event.
+**/
+VOID
+EFIAPI
+CheckAPsStatus (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+#endif
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/ProcessorData.c b/ReferenceCode/Haswell/CpuInit/Dxe/ProcessorData.c
new file mode 100644
index 0000000..f3a47a5
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/ProcessorData.c
@@ -0,0 +1,795 @@
+/** @file
+ Produces CPU data records.
+
+Revision History
+
+@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 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
+
+**/
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "ProcessorData.h"
+#include "MpCommon.h"
+#include "MpService.h"
+
+///
+/// This is the VFR compiler generated header file which defines the
+/// string identifiers.
+///
+#include "CpuInitDxeStrDefs.h"
+
+#endif
+
+extern MP_SYSTEM_DATA *mMPSystemData;
+extern DXE_CPU_PLATFORM_POLICY_PROTOCOL *mPlatformCpu;
+
+#if (EFI_SPECIFICATION_VERSION < 0x2000A)
+extern EFI_HII_PROTOCOL *mHii;
+#endif
+extern EFI_DATA_HUB_PROTOCOL *mDataHub;
+extern DXE_CPU_PLATFORM_POLICY_PROTOCOL *mPlatformCpu;
+extern EFI_HII_HANDLE mStringHandle;
+
+EFI_SUBCLASS_TYPE1_HEADER mCpuDataRecordHeader = {
+ EFI_PROCESSOR_SUBCLASS_VERSION, ///< Version
+ sizeof (EFI_SUBCLASS_TYPE1_HEADER), ///< Header Size
+ 0, ///< Instance, Initialize later
+ EFI_SUBCLASS_INSTANCE_NON_APPLICABLE, ///< SubInstance
+ 0 ///< RecordType, Initialize later
+};
+
+EFI_STATUS
+LogCpuData (
+ EFI_DATA_HUB_PROTOCOL *DataHub,
+ UINT8 *Buffer,
+ UINT32 Size
+ );
+
+typedef struct _PROCESSOR_FAMILY_FIELD {
+ CHAR8 ProcessorFamily[48];
+ UINT16 ProcessorEnum;
+} PROCESSOR_FAMILY_FIELD;
+
+PROCESSOR_FAMILY_FIELD ProcessorFamilyField[] = {
+ {
+ "Intel(R) Core(TM) i7",
+ 0xC6
+ },
+ {
+ "Intel(R) Core(TM) i5",
+ 0xCD
+ },
+ {
+ "Intel(R) Core(TM) i3",
+ 0xCE
+ },
+ {
+ "Intel(R) Xeon(R) CPU",
+ 0xB3
+ },
+ {
+ "Intel(R) Pentium(R) CPU",
+ 0x0B
+ },
+ {
+ "Intel(R) Celeron(R) CPU",
+ 0x0F
+ },
+};
+
+/**
+ Converts an ascii string to unicode string 16 chars at a time.
+
+ @param[in] AsciiString - Pointer to input Ascii string.
+ @param[in] UnicodeString - Pointer to output Unicode string buffer.
+**/
+VOID
+AsciiToUnicode (
+ IN CHAR8 *AsciiString,
+ IN OUT CHAR16 *UnicodeString
+ )
+{
+ UINT8 Index;
+
+ for (Index = 0; Index < 16; Index++) {
+ UnicodeString[Index] = (CHAR16) AsciiString[Index];
+ }
+
+ return;
+}
+///
+/// Processor-specific routines
+///
+/**
+ Returns the procesor version string token installed in the system.
+
+ @retval Processor Version string token
+**/
+VOID
+GetProcessorVersion (
+ OUT PROCESSOR_VERSION_INFORMATION *Version
+ )
+{
+ CHAR16 BrandIdString[MAXIMUM_CPU_BRAND_STRING_LENGTH + 1];
+ EFI_CPUID_REGISTER CpuExtendedSupport;
+ EFI_CPUID_REGISTER CpuBrandString;
+ UINT8 Index;
+
+ ///
+ /// Create the string using Brand ID String.
+ ///
+ Version->StringValid = FALSE;
+
+ if (IsIntelProcessor ()) {
+ Version->StringRef = STRING_TOKEN (STR_INTEL_GENUINE_PROCESSOR);
+
+ AsmCpuid (
+ CPUID_EXTENDED_FUNCTION,
+ &CpuExtendedSupport.RegEax,
+ &CpuExtendedSupport.RegEbx,
+ &CpuExtendedSupport.RegEcx,
+ &CpuExtendedSupport.RegEdx
+ );
+ AsmCpuid (
+ CPUID_BRAND_STRING1,
+ &CpuBrandString.RegEax,
+ &CpuBrandString.RegEbx,
+ &CpuBrandString.RegEcx,
+ &CpuBrandString.RegEdx
+ );
+ ///
+ /// Check if Brand ID String is supported or filled up
+ ///
+ if (CpuExtendedSupport.RegEax != 0 && CpuBrandString.RegEax != 0) {
+ AsciiToUnicode ((CHAR8 *) &CpuBrandString, (CHAR16 *) &BrandIdString[0]);
+ AsmCpuid (
+ CPUID_BRAND_STRING2,
+ &CpuBrandString.RegEax,
+ &CpuBrandString.RegEbx,
+ &CpuBrandString.RegEcx,
+ &CpuBrandString.RegEdx
+ );
+ AsciiToUnicode ((CHAR8 *) &CpuBrandString, (CHAR16 *) &BrandIdString[16]);
+ AsmCpuid (
+ CPUID_BRAND_STRING3,
+ &CpuBrandString.RegEax,
+ &CpuBrandString.RegEbx,
+ &CpuBrandString.RegEcx,
+ &CpuBrandString.RegEdx
+ );
+ AsciiToUnicode ((CHAR8 *) &CpuBrandString, (CHAR16 *) &BrandIdString[32]);
+
+ ///
+ /// Remove preceeding spaces
+ ///
+ Index = 0;
+ while (BrandIdString[Index] == 0x20) {
+ Index++;
+ if (Index >= MAXIMUM_CPU_BRAND_STRING_LENGTH) {
+ break;
+ }
+ }
+
+ CopyMem (
+ Version->BrandString,
+ &BrandIdString[Index],
+ (MAXIMUM_CPU_BRAND_STRING_LENGTH - Index) * sizeof (CHAR16)
+ );
+ Version->BrandString[MAXIMUM_CPU_BRAND_STRING_LENGTH - Index] = 0;
+ Version->StringValid = TRUE;
+ }
+ } else {
+ Version->StringRef = STRING_TOKEN (STR_UNKNOWN);
+ }
+}
+
+/**
+ Returns the procesor manufaturer string token installed in the system.
+
+ @retval Processor Manufacturer string token
+**/
+EFI_PROCESSOR_MANUFACTURER_DATA
+GetProcessorManufacturer (
+ VOID
+ )
+{
+
+ if (IsIntelProcessor ()) {
+ return STRING_TOKEN (STR_INTEL_CORPORATION);
+ } else {
+ return STRING_TOKEN (STR_UNKNOWN);
+ }
+}
+
+/**
+ Returns if processor is Intel or not.
+
+ @retval TRUE - Intel Processor.
+ @retval FALSE - Not Intel Processor.
+**/
+BOOLEAN
+IsIntelProcessor (
+ VOID
+ )
+{
+ EFI_CPUID_REGISTER Reg;
+
+ AsmCpuid (CPUID_SIGNATURE, &Reg.RegEax, &Reg.RegEbx, &Reg.RegEcx, &Reg.RegEdx);
+
+ if ((Reg.RegEbx != 'uneG') || (Reg.RegEdx != 'Ieni') || (Reg.RegEcx != 'letn')) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+/**
+ Returns the processor family of the processor installed in the system.
+
+ @retval Processor Family
+**/
+EFI_PROCESSOR_FAMILY_DATA
+GetProcessorFamily (
+ VOID
+ )
+{
+
+ UINTN j;
+ UINTN Index;
+ EFI_CPUID_REGISTER CpuExtendedSupport;
+ EFI_CPUID_REGISTER CpuBrandString;
+ CHAR8 BrandString[MAXIMUM_CPU_BRAND_STRING_LENGTH + 1];
+ UINT16 ProcessorFamily;
+ ProcessorFamily = EfiProcessorFamilyUnknown;
+ Index = 0;
+
+ if (IsIntelProcessor ()) {
+ ///
+ /// Get Brand string
+ ///
+ AsmCpuid (
+ CPUID_EXTENDED_FUNCTION,
+ &CpuExtendedSupport.RegEax,
+ &CpuExtendedSupport.RegEbx,
+ &CpuExtendedSupport.RegEcx,
+ &CpuExtendedSupport.RegEdx
+ );
+ AsmCpuid (
+ CPUID_BRAND_STRING1,
+ &CpuBrandString.RegEax,
+ &CpuBrandString.RegEbx,
+ &CpuBrandString.RegEcx,
+ &CpuBrandString.RegEdx
+ );
+
+ if (CpuExtendedSupport.RegEax != 0 && CpuBrandString.RegEax != 0) {
+ EfiAsciiStrCpy (&BrandString[0], (CHAR8 *) &CpuBrandString);
+ AsmCpuid (
+ CPUID_BRAND_STRING2,
+ &CpuBrandString.RegEax,
+ &CpuBrandString.RegEbx,
+ &CpuBrandString.RegEcx,
+ &CpuBrandString.RegEdx
+ );
+ EfiAsciiStrCpy (&BrandString[16], (CHAR8 *) &CpuBrandString);
+ AsmCpuid (
+ CPUID_BRAND_STRING3,
+ &CpuBrandString.RegEax,
+ &CpuBrandString.RegEbx,
+ &CpuBrandString.RegEcx,
+ &CpuBrandString.RegEdx
+ );
+ EfiAsciiStrCpy (&BrandString[32], (CHAR8 *) &CpuBrandString);
+
+ ///
+ /// Remove preceeding spaces
+ ///
+ while (BrandString[Index] == 0x20) {
+ Index++;
+ }
+
+ BrandString[MAXIMUM_CPU_BRAND_STRING_LENGTH - Index] = 0;
+ }
+
+ ProcessorFamily = 0xC6;
+
+ for (j = 0; j < sizeof (ProcessorFamilyField) / sizeof (PROCESSOR_FAMILY_FIELD); j++) {
+ if (EfiAsciiStrnCmp (
+ &BrandString[Index],
+ ProcessorFamilyField[j].ProcessorFamily,
+ (EfiAsciiStrLen (ProcessorFamilyField[j].ProcessorFamily))
+ ) == 0) {
+ ProcessorFamily = ProcessorFamilyField[j].ProcessorEnum;
+ break;
+ }
+ }
+ } else {
+ ProcessorFamily = EfiProcessorFamilyOther;
+ }
+
+ return ProcessorFamily;
+}
+
+/**
+ Returns the processor voltage of the processor installed in the system.
+
+ @retval Processor Voltage
+**/
+INT16
+GetProcessorVoltage (
+ VOID
+ )
+{
+ INT16 VoltageInmV;
+ UINT64 MsrValue;
+
+ VoltageInmV = 0;
+ MsrValue = 0;
+
+ ///
+ /// Core voltage = (float) IA32_PERF_STS(47:32) * (float) 1/(2^13)
+ ///
+ MsrValue = AsmReadMsr64 (MSR_IA32_PERF_STS);
+ MsrValue = RShiftU64(MsrValue, 32);
+ MsrValue &= 0x0FFFF;
+
+ ///
+ /// Convert unit to mV
+ ///
+ MsrValue = MultU64x32(MsrValue, 1000);
+ MsrValue = RShiftU64 (MsrValue, 13);
+ VoltageInmV = (UINT16) MsrValue;
+
+ return VoltageInmV;
+}
+
+/**
+ Returns the processor microcode revision of the processor installed in the system.
+
+ @retval Processor Microcode Revision
+**/
+UINT32
+GetCpuUcodeRevision (
+ VOID
+ )
+{
+ AsmWriteMsr64 (MSR_IA32_BIOS_SIGN_ID, 0);
+ EfiCpuid (CPUID_VERSION_INFO, NULL);
+ return (UINT32) RShiftU64 (AsmReadMsr64 (MSR_IA32_BIOS_SIGN_ID), 32);
+}
+
+/**
+ Get processor status by specific CPU number
+
+ @param[in] CpuNumber - indicate which CPU status are requested
+
+ @retval EFI_PROCESSOR_STATUS_DATA for specific CPU number
+**/
+EFI_PROCESSOR_STATUS_DATA
+GetProcessorStatus (
+ IN UINTN CpuNumber
+ )
+{
+ EFI_PROCESSOR_STATUS_DATA ProcessorStatus;
+ CPU_DATA_BLOCK *CpuData;
+
+ CpuData = &mMPSystemData->CpuData[CpuNumber];
+
+ ProcessorStatus.Reserved1 = 0;
+ ProcessorStatus.Reserved2 = 0;
+ ProcessorStatus.Reserved3 = 0;
+
+ ProcessorStatus.CpuStatus = EfiCpuStatusEnabled;
+ if (CpuData->State == CPU_STATE_DISABLED) {
+ switch (mMPSystemData->DisableCause[CpuNumber]) {
+ case CPU_CAUSE_USER_SELECTION:
+ case CPU_CAUSE_BY_ASSOCIATION:
+ ProcessorStatus.CpuStatus = EfiCpuStatusDisabledByUser;
+ break;
+
+ case CPU_CAUSE_INTERNAL_ERROR:
+ case CPU_CAUSE_THERMAL_ERROR:
+ case CPU_CAUSE_SELFTEST_FAILURE:
+ case CPU_CAUSE_PREBOOT_TIMEOUT:
+ case CPU_CAUSE_CONFIG_ERROR:
+ ProcessorStatus.CpuStatus = EfiCpuStatusDisabledbyBios;
+ break;
+
+ case CPU_CAUSE_FAILED_TO_START:
+ case CPU_CAUSE_UNSPECIFIED:
+ default:
+ ProcessorStatus.CpuStatus = EfiCpuStatusOther;
+ break;
+ }
+ }
+
+ ProcessorStatus.SocketPopulated = TRUE;
+ ProcessorStatus.ApicEnable = 1;
+
+ if (mMPSystemData->BSP == CpuNumber) {
+ ProcessorStatus.BootApplicationProcessor = 1;
+ } else {
+ ProcessorStatus.BootApplicationProcessor = 0;
+ }
+
+ return ProcessorStatus;
+}
+
+/**
+ This function gets called with the processor number and will log all data to data hub
+ pertaining to this processor.
+
+ @param[in] CpuNumber - Processor Number
+ @param[in] CpuDataForDatahub - Contains CPU data which is collected for data hub
+
+ @retval EFI_OUT_OF_RESOURCES - failed to allocate pool for CPU data
+ @retval EFI_SUCCESS - CPU data Hub has been created successfully
+**/
+EFI_STATUS
+InitializeProcessorData (
+ IN UINTN CpuNumber,
+ IN CPU_DATA_FOR_DATAHUB *CpuDataForDatahub
+ )
+{
+ EFI_STATUS Status;
+ EFI_CPU_DATA_RECORD_BUFFER RecordBuffer;
+ UINT32 HeaderSize;
+ UINT32 TotalSize;
+ PLATFORM_CPU_INFORMATION PlatformCpuInfo;
+ STRING_REF Token;
+ UINT64 MsrValue;
+ UINT64 ProcessorCoreCount;
+ UINT64 ProcessorThreadCount;
+
+ mCpuDataRecordHeader.Instance = (UINT16) (CpuNumber + 1);
+
+ HeaderSize = sizeof (EFI_SUBCLASS_TYPE1_HEADER);
+ RecordBuffer.Raw = AllocatePool (HeaderSize + EFI_CPU_DATA_MAXIMUM_LENGTH);
+ if (RecordBuffer.Raw == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ZeroMem (&PlatformCpuInfo, sizeof (PLATFORM_CPU_INFORMATION));
+ CopyMem (RecordBuffer.Raw, &mCpuDataRecordHeader, HeaderSize);
+
+ ///
+ /// Record following data by socket base
+ ///
+ if (CpuNumber == 0) {
+ ///
+ /// Record Type 1
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorCoreFrequencyRecordType;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorCoreFrequency.Value = (UINT16) CpuDataForDatahub->IntendCoreFrequency;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorCoreFrequency.Exponent = 6;
+ TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_CORE_FREQUENCY_DATA);
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 2
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorFsbFrequencyRecordType;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorFsbFrequency.Value = 100;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorFsbFrequency.Exponent = 6;
+ TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_FSB_FREQUENCY_DATA);
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 3
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorVersionRecordType;
+ if (CpuDataForDatahub->Version.StringValid) {
+ Token = 0;
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
+ Status = IfrLibNewString (mStringHandle, &Token, CpuDataForDatahub->Version.BrandString);
+#else
+ Status = mHii->NewString (mHii, NULL, mStringHandle, &Token, CpuDataForDatahub->Version.BrandString);
+#endif
+ if (EFI_ERROR (Status)) {
+ Token = CpuDataForDatahub->Version.StringRef;
+ }
+ } else {
+ Token = CpuDataForDatahub->Version.StringRef;
+ }
+
+ RecordBuffer.DataRecord->VariableRecord.ProcessorVersion = Token;
+ TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_VERSION_DATA);
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 4
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorManufacturerRecordType;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorManufacturer = CpuDataForDatahub->Manufacturer;
+ TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_MANUFACTURER_DATA);
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 6.
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorIdRecordType;
+ CopyMem (
+ &RecordBuffer.DataRecord->VariableRecord.ProcessorId,
+ &CpuDataForDatahub->CpuidData,
+ sizeof (CpuDataForDatahub->CpuidData)
+ );
+ TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_ID_DATA);
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 7.
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorTypeRecordType;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorType = EfiCentralProcessor;
+ TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_TYPE_DATA);
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 8.
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorFamilyRecordType;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorFamily = CpuDataForDatahub->Family;
+ TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_FAMILY_DATA);
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 9.
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorVoltageRecordType;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorVoltage.Value = CpuDataForDatahub->Voltage;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorVoltage.Exponent = -3;
+ TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_VOLTAGE_DATA);
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+ }
+ ///
+ /// log data by socket base
+ ///
+ /// Record Type 10.
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorApicBaseAddressRecordType;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorApicBase = CpuDataForDatahub->ApicBase;
+ TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_APIC_BASE_ADDRESS_DATA);
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 11.
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorApicIdRecordType;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorApicId = CpuDataForDatahub->ApicID;
+ TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_APIC_ID_DATA);
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 12.
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorApicVersionNumberRecordType;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorApicVersionNumber = CpuDataForDatahub->ApicVersion;
+ TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_APIC_VERSION_NUMBER_DATA);
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 13.
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = CpuUcodeRevisionDataRecordType;
+ RecordBuffer.DataRecord->VariableRecord.CpuUcodeRevisionData.ProcessorMicrocodeType = EfiProcessorIa32Microcode;
+ RecordBuffer.DataRecord->VariableRecord.CpuUcodeRevisionData.ProcessorMicrocodeRevisionNumber = CpuDataForDatahub->MicrocodeRevision;
+ TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_MICROCODE_REVISION_DATA);
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record following data by socket base
+ ///
+ if (CpuNumber == 0) {
+ ///
+ /// Record Type 14.
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorStatusRecordType;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorStatus = CpuDataForDatahub->Status;
+ TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_STATUS_DATA);
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 17(0x11). Set in Cache File
+ ///
+ ///
+ /// Record Type 21(0x15). zero based
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorPackageNumberRecordType;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorPackageNumber = CpuDataForDatahub->Location.Package;
+ TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_PACKAGE_NUMBER_DATA);
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 24(0x18).
+ /// Health definition in DataHub spec is not the same as BIST format, so add 1 to convert
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorHealthStatusRecordType;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorHealthStatus = CpuDataForDatahub->Health.Uint32 + 1;
+ TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_HEALTH_STATUS);
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+ }
+ ///
+ /// log data by socket base
+ ///
+ /// The following record data comes from platform driver:
+ ///
+ PlatformCpuInfo.StringHandle = mStringHandle;
+ PlatformCpuInfo.ApicID = CpuDataForDatahub->ApicID;
+ Status = mPlatformCpu->CpuConfig->GetCpuInfo (
+ mPlatformCpu,
+ &CpuDataForDatahub->Location,
+ &PlatformCpuInfo
+ );
+
+ ///
+ /// Record following data by socket base
+ ///
+ if (CpuNumber == 0) {
+ ///
+ /// Record Type 5. (Processor Serial Number: this feature is only available on PIII, not support here)
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorSerialNumberRecordType;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorAssetTag = PlatformCpuInfo.SerialNumber;
+ TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_SERIAL_NUMBER_DATA);
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 15.
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorSocketTypeRecordType;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorSocketType = PlatformCpuInfo.SocketType;
+ TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_SOCKET_TYPE_DATA);
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 16(0x10).
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorSocketNameRecordType;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorSocketName = PlatformCpuInfo.SocketName;
+ TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_SOCKET_NAME_DATA);
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 18(0x12).
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorMaxCoreFrequencyRecordType;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorMaxCoreFrequency = PlatformCpuInfo.MaxCoreFrequency;
+ TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_MAX_CORE_FREQUENCY_DATA);
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 19(0x13).
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorAssetTagRecordType;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorAssetTag = PlatformCpuInfo.AssetTag;
+ TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_ASSET_TAG_DATA);
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+ }
+ ///
+ /// log data by socket base
+ ///
+ /// Record Type 20(0x14).
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorMaxFsbFrequencyRecordType;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorMaxFsbFrequency = PlatformCpuInfo.MaxFsbFrequency;
+ TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_MAX_FSB_FREQUENCY_DATA);
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 22(0x16).
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorCoreFrequencyListRecordType;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorCoreFrequencyList = PlatformCpuInfo.PlatformCoreFrequencyList;
+ TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_CORE_FREQUENCY_LIST_DATA);
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 23(0x17).
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorFsbFrequencyListRecordType;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorFsbFrequencyList = PlatformCpuInfo.PlatformFsbFrequencyList;
+ TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_FSB_FREQUENCY_LIST_DATA);
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record following data by socket base
+ ///
+ if (CpuNumber == 0) {
+ ///
+ /// Record Type 30. (Processor Part Number)
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorPartNumberRecordType;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorAssetTag = PlatformCpuInfo.PartNumber;
+ TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_PART_NUMBER_DATA);
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 28.
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorCharacteristicsRecordType;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorCharacteristics.Reserved2 = 0;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorCharacteristics.Reserved = 0;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorCharacteristics.Unknown = 0;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorCharacteristics.Capable64Bit = 1;
+ TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_CHARACTERISTICS_DATA);
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ MsrValue = AsmReadMsr64 (MSR_CORE_THREAD_COUNT);
+ ProcessorThreadCount = MsrValue & 0xffff;
+ ProcessorCoreCount = (MsrValue >> 16) & 0xffff;
+
+ ///
+ /// Record Type 25.
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorCoreCountRecordType;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorCoreCount = (UINT8) (ProcessorCoreCount);
+ TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_CORE_COUNT_DATA);
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 26.
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorEnabledCoreCountRecordType;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorEnabledCoreCount = (UINT8) (ProcessorCoreCount);
+ TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_ENABLED_CORE_COUNT_DATA);
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+
+ ///
+ /// Record Type 27.
+ ///
+ RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorThreadCountRecordType;
+ RecordBuffer.DataRecord->VariableRecord.ProcessorThreadCount = (UINT8) (ProcessorThreadCount);
+ TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_THREAD_COUNT_DATA);
+ Status = LogCpuData (mDataHub, RecordBuffer.Raw, TotalSize);
+ }
+ ///
+ /// log data by socket base
+ ///
+ FreePool (RecordBuffer.Raw);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Log CPU data into data hub
+
+ @param[in] DataHub - point to data hub that will be updated
+ @param[in] Buffer - the buffer which will be updated into data hub
+ @param[in] Size - size of the buffer
+
+ @retval EFI_STATUS - status returned when updating Data hub
+**/
+EFI_STATUS
+LogCpuData (
+ EFI_DATA_HUB_PROTOCOL *DataHub,
+ UINT8 *Buffer,
+ UINT32 Size
+ )
+{
+ EFI_STATUS Status;
+
+ Status = DataHub->LogData (
+ DataHub,
+ &gEfiProcessorSubClassGuid,
+ &gEfiProcessorProducerGuid,
+ EFI_DATA_RECORD_CLASS_DATA,
+ Buffer,
+ Size
+ );
+ return Status;
+
+}
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/ProcessorData.h b/ReferenceCode/Haswell/CpuInit/Dxe/ProcessorData.h
new file mode 100644
index 0000000..fea963e
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/ProcessorData.h
@@ -0,0 +1,136 @@
+/** @file
+ Header file for CPU Data File
+
+Revision History
+
+@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 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
+**/
+#ifndef _PROCESSOR_DATA_H_
+#define _PROCESSOR_DATA_H_
+
+#include "CpuInitDxe.h"
+
+#define EFI_PROCESSOR_TYPE_SIZE 6
+
+typedef struct {
+ UINT8 Index;
+ UINT8 ProcessorFamily;
+ STRING_REF ProcessorVersionToken;
+} EFI_PROCESSOR_VERSION;
+
+typedef struct {
+ UINT32 Dword1;
+ UINT32 Dword2;
+ UINT32 Dword3;
+ UINT32 Dword4;
+} EFI_QDWORD;
+
+///
+/// Platform-specific definitions
+///
+#define EFI_CPU_DATA_MAXIMUM_LENGTH 0x100
+
+/**
+ This function gets called with the processor number and will log all data to data hub
+ pertaining to this processor.
+
+ @param[in] CpuNumber - Processor Number
+ @param[in] CpuDataForDatahub - Contains CPU data which is collected for data hub
+
+ @retval EFI_OUT_OF_RESOURCES - failed to allocate pool for CPU data
+ @retval EFI_SUCCESS - CPU data Hub has been created successfully
+**/
+EFI_STATUS
+InitializeProcessorData (
+ IN UINTN CpuNumber,
+ IN CPU_DATA_FOR_DATAHUB *CpuDataForDatahub
+ );
+
+/**
+ Returns the processor voltage of the processor installed in the system.
+
+ @retval Processor Voltage
+**/
+INT16
+GetProcessorVoltage (
+ VOID
+ );
+
+/**
+ Returns the processor microcode revision of the processor installed in the system.
+
+ @retval Processor Microcode Revision
+**/
+UINT32
+GetCpuUcodeRevision (
+ VOID
+ );
+
+/**
+ Get processor status by specific CPU number
+
+ @param[in] CpuNumber - indicate which CPU status are requested
+
+ @retval EFI_PROCESSOR_STATUS_DATA for specific CPU number
+**/
+EFI_PROCESSOR_STATUS_DATA
+GetProcessorStatus (
+ UINTN CpuNumber
+ );
+
+/**
+ Returns the procesor version string token installed in the system.
+
+ @retval Processor Version string token
+**/
+VOID
+GetProcessorVersion (
+ OUT PROCESSOR_VERSION_INFORMATION *Version
+ );
+
+/**
+ Returns the processor family of the processor installed in the system.
+
+ @retval Processor Family
+**/
+EFI_PROCESSOR_FAMILY_DATA
+GetProcessorFamily (
+ VOID
+ );
+
+/**
+ Returns the procesor manufaturer string token installed in the system.
+
+ @retval Processor Manufacturer string token
+**/
+EFI_PROCESSOR_MANUFACTURER_DATA
+GetProcessorManufacturer (
+ VOID
+ );
+
+/**
+ Returns if processor is Intel or not.
+
+ @retval TRUE - Intel Processor.
+ @retval FALSE - Not Intel Processor.
+**/
+BOOLEAN
+IsIntelProcessor (
+ VOID
+ );
+
+#endif
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/x64/Cpu.asm b/ReferenceCode/Haswell/CpuInit/Dxe/x64/Cpu.asm
new file mode 100644
index 0000000..9b28b54
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/x64/Cpu.asm
@@ -0,0 +1,626 @@
+;
+; 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
+;
+ TITLE Cpu.asm: Assembly code for the IA-32 resources
+
+;-------------------------------------------------------------------------------
+;
+; Copyright (c) 2005 -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.
+;
+;
+; Module Name:
+;
+; Cpu.asm
+;
+; Abstract:
+;
+;
+;-------------------------------------------------------------------------------
+
+text SEGMENT
+
+EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions
+
+ExternalVectorTablePtr QWORD 0 ; point to the external interrupt vector table
+
+;
+; Float control word initial value:
+; all exceptions masked, double-extended-precision, round-to-nearest
+;
+mFpuControlWord DW 037Fh
+;
+; Multimedia-extensions control word:
+; all exceptions masked, round-to-nearest, flush to zero for masked underflow
+;
+mMmxControlWord DD 01F80h
+
+
+InitializeExternalVectorTablePtr PROC PUBLIC
+ mov ExternalVectorTablePtr, rcx
+ ret
+InitializeExternalVectorTablePtr ENDP
+;
+;
+;
+;------------------------------------------------------------------------------
+; Generic IDT Vector Handlers for the Host. They are all the same so they
+; will compress really well.
+;
+; By knowing the return address for Vector 00 you can can calculate the
+; vector number by looking at the call CommonInterruptEntry return address.
+; (return address - (AsmIdtVector00 + 5))/8 == IDT index
+;
+;------------------------------------------------------------------------------
+
+ALIGN 8
+
+PUBLIC AsmIdtVector00
+
+AsmIdtVector00 LABEL BYTE
+REPEAT 256
+ call CommonInterruptEntry
+ dw ( $ - AsmIdtVector00 - 5 ) / 8 ; vector number
+ nop
+ENDM
+
+
+;---------------------------------------;
+; CommonInterruptEntry ;
+;---------------------------------------;
+; The follow algorithm is used for the common interrupt routine.
+
+;
+; +---------------------+ <-- 16-byte aligned ensured by processor
+; + Old SS +
+; +---------------------+
+; + Old RSP +
+; +---------------------+
+; + RFlags +
+; +---------------------+
+; + CS +
+; +---------------------+
+; + RIP +
+; +---------------------+
+; + Error Code +
+; +---------------------+
+; + RCX / Vector Number +
+; +---------------------+
+; + RBP +
+; +---------------------+ <-- RBP, 16-byte aligned
+;
+
+CommonInterruptEntry PROC PUBLIC
+ cli
+ cld
+ ;
+ ; All interrupt handlers are invoked through interrupt gates, so
+ ; IF flag automatically cleared at the entry point
+ ;
+ ;
+ ; Calculate vector number
+ ;
+ xchg rcx, [rsp] ; get the return address of call, actually, it is the address of vector number.
+ movzx ecx, word ptr [rcx]
+ cmp ecx, 32 ; Intel reserved vector for exceptions?
+ jae NoErrorCode
+ bt mErrorCodeFlag, ecx
+ jc @F
+
+NoErrorCode:
+ ;
+ ; Push a dummy error code on the stack
+ ; to maintain coherent stack map
+ ;
+ push [rsp]
+ mov qword ptr [rsp + 8], 0
+@@:
+ push rbp
+ mov rbp, rsp
+
+ ;
+ ; Since here the stack pointer is 16-byte aligned, so
+ ; EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64
+ ; is 16-byte aligned
+ ;
+
+;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
+;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
+ push r15
+ push r14
+ push r13
+ push r12
+ push r11
+ push r10
+ push r9
+ push r8
+ push rax
+ push qword ptr [rbp + 8] ; RCX
+ push rdx
+ push rbx
+ push qword ptr [rbp + 48] ; RSP
+ push qword ptr [rbp] ; RBP
+ push rsi
+ push rdi
+
+;; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero
+ movzx rax, word ptr [rbp + 56]
+ push rax ; for ss
+ movzx rax, word ptr [rbp + 32]
+ push rax ; for cs
+ mov rax, ds
+ push rax
+ mov rax, es
+ push rax
+ mov rax, fs
+ push rax
+ mov rax, gs
+ push rax
+
+ mov [rbp + 8], rcx ; save vector number
+
+;; UINT64 Rip;
+ push qword ptr [rbp + 24]
+
+;; UINT64 Gdtr[2], Idtr[2];
+ sub rsp, 16
+ sidt fword ptr [rsp]
+ sub rsp, 16
+ sgdt fword ptr [rsp]
+
+;; UINT64 Ldtr, Tr;
+ xor rax, rax
+ str ax
+ push rax
+ sldt ax
+ push rax
+
+;; UINT64 RFlags;
+ push qword ptr [rbp + 40]
+
+;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
+ mov rax, cr8
+ push rax
+ mov rax, cr4
+ or rax, 208h
+ mov cr4, rax
+ push rax
+ mov rax, cr3
+ push rax
+ mov rax, cr2
+ push rax
+ xor rax, rax
+ push rax
+ mov rax, cr0
+ push rax
+
+;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ mov rax, dr7
+ push rax
+;; clear Dr7 while executing debugger itself
+ xor rax, rax
+ mov dr7, rax
+
+ mov rax, dr6
+ push rax
+;; insure all status bits in dr6 are clear...
+ xor rax, rax
+ mov dr6, rax
+
+ mov rax, dr3
+ push rax
+ mov rax, dr2
+ push rax
+ mov rax, dr1
+ push rax
+ mov rax, dr0
+ push rax
+
+;; FX_SAVE_STATE_X64 FxSaveState;
+
+ sub rsp, 512
+ mov rdi, rsp
+ db 0fh, 0aeh, 00000111y ;fxsave [rdi]
+
+;; UINT32 ExceptionData;
+ push qword ptr [rbp + 16]
+
+;; call into exception handler
+ mov rcx, [rbp + 8]
+ mov rax, ExternalVectorTablePtr ; get the interrupt vectors base
+ mov rax, [rax + rcx * 8]
+ or rax, rax ; NULL?
+
+ je nonNullValue;
+
+;; Prepare parameter and call
+; mov rcx, [rbp + 8]
+ mov rdx, rsp
+ ;
+ ; Per X64 calling convention, allocate maximum parameter stack space
+ ; and make sure RSP is 16-byte aligned
+ ;
+ sub rsp, 4 * 8 + 8
+ call rax
+ add rsp, 4 * 8 + 8
+
+nonNullValue:
+ cli
+;; UINT64 ExceptionData;
+ add rsp, 8
+
+;; FX_SAVE_STATE_X64 FxSaveState;
+
+ mov rsi, rsp
+ db 0fh, 0aeh, 00001110y ; fxrstor [rsi]
+ add rsp, 512
+
+;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ pop rax
+ mov dr0, rax
+ pop rax
+ mov dr1, rax
+ pop rax
+ mov dr2, rax
+ pop rax
+ mov dr3, rax
+;; skip restore of dr6. We cleared dr6 during the context save.
+ add rsp, 8
+ pop rax
+ mov dr7, rax
+
+;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
+ pop rax
+ mov cr0, rax
+ add rsp, 8 ; not for Cr1
+ pop rax
+ mov cr2, rax
+ pop rax
+ mov cr3, rax
+ pop rax
+ mov cr4, rax
+ pop rax
+ mov cr8, rax
+
+;; UINT64 RFlags;
+ pop qword ptr [rbp + 40]
+
+;; UINT64 Ldtr, Tr;
+;; UINT64 Gdtr[2], Idtr[2];
+;; Best not let anyone mess with these particular registers...
+ add rsp, 48
+
+;; UINT64 Rip;
+ pop qword ptr [rbp + 24]
+
+;; UINT64 Gs, Fs, Es, Ds, Cs, Ss;
+ pop rax
+ ; mov gs, rax ; not for gs
+ pop rax
+ ; mov fs, rax ; not for fs
+ ; (X64 will not use fs and gs, so we do not restore it)
+ pop rax
+ mov es, rax
+ pop rax
+ mov ds, rax
+ pop qword ptr [rbp + 32] ; for cs
+ pop qword ptr [rbp + 56] ; for ss
+
+;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
+;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
+ pop rdi
+ pop rsi
+ add rsp, 8 ; not for rbp
+ pop qword ptr [rbp + 48] ; for rsp
+ pop rbx
+ pop rdx
+ pop rcx
+ pop rax
+ pop r8
+ pop r9
+ pop r10
+ pop r11
+ pop r12
+ pop r13
+ pop r14
+ pop r15
+
+ mov rsp, rbp
+ pop rbp
+ add rsp, 16
+ iretq
+
+CommonInterruptEntry ENDP
+
+
+LongMode PROC PUBLIC
+
+in_long_mode::
+ ;
+ ; Debug Stop
+ ;
+ jmp in_long_mode
+
+ ;
+ ; We're in long mode, so marshall the arguments to call the
+ ; passed in function pointers
+ ; Recall
+ ; [ebp][10h] = HobStart
+ ; [ebp][18h] = Stack
+ ; [ebp][20h] = PpisNeededByDxeIplEntryPoint <--- Call this first (for each call, pass HOB pointer)
+ ; [ebp][28h] = DxeCoreEntryPoint <--- Call this second
+ ;
+ mov rbx, [rbp+18h] ; Setup the stack
+ mov rsp, rbx ; On a new stack now
+
+ mov rcx, [rbp+10h] ; Pass Hob Start in RCX
+ mov rax, [rbp+20h] ; Get the function pointer for
+ ; PpisNeededByDxeIplEntryPoint into EAX
+ call fword ptr [rax] ; Make the call into PpisNeededByDxeIplEntryPoint
+
+ mov ecx, [rbp+10h] ; Pass Hob Start in RCX
+ mov eax, [rbp+28h] ; Get the function pointer for
+ ; DxeCoreEntryPoint into EAX
+ call fword ptr [rax] ; Make the call into Dxe Core
+
+ call CommonInterruptEntry
+
+ mov rdi, CommonInterruptEntry
+
+ lgdt fword ptr [rdi]
+
+ lidt fword ptr [rdi]
+
+ call near ptr [rax] ; Make the call into PpisNeededByDxeIplEntryPoint
+
+ call rax
+
+ ;
+ ; Should never get here.
+ ;
+no_long_mode:
+ jmp no_long_mode
+ ;
+ ; WE SHOULD NEVER GET HERE!!!!!!!!!!!!!
+ ;
+LongMode endp
+
+EnableMce proc public
+
+ mov rax, cr4
+ or rax, 40h
+ mov cr4, rax
+
+ ret
+
+EnableMce endp
+
+MpMtrrSynchUpEntry PROC PUBLIC
+ ;
+ ; Enter no fill cache mode, CD=1(Bit30), NW=0 (Bit29)
+ ;
+ mov rax, cr0
+ and rax, 0DFFFFFFFh
+ or rax, 040000000h
+ mov cr0, rax
+ ;
+ ; Flush cache
+ ;
+ wbinvd
+ ;
+ ; Clear PGE flag Bit 7
+ ;
+ mov rax, cr4
+ mov rdx, rax
+ and rax, 0FFFFFF7Fh
+ mov cr4, rax
+ ;
+ ; Flush all TLBs
+ ;
+ mov rax, cr3
+ mov cr3, rax
+
+ mov rax, rdx
+
+ ret
+
+MpMtrrSynchUpEntry ENDP
+
+MpMtrrSynchUpExit PROC PUBLIC
+ ;
+ ; Flush all TLBs the second time
+ ;
+ mov rax, cr3
+ mov cr3, rax
+ ;
+ ; Enable Normal Mode caching CD=NW=0, CD(Bit30), NW(Bit29)
+ ;
+ mov rax, cr0
+ and rax, 09FFFFFFFh
+ mov cr0, rax
+ ;
+ ; Set PGE Flag in CR4 if set
+ ;
+ mov cr4, rcx
+ ret
+
+MpMtrrSynchUpExit ENDP
+
+;
+; Initializes floating point units for requirement of UEFI specification.
+;
+; This function initializes floating-point control word to 0x037F (all exceptions
+; masked,double-extended-precision, round-to-nearest) and multimedia-extensions control word
+; (if supported) to 0x1F80 (all exceptions masked, round-to-nearest, flush to zero
+; for masked underflow).
+;
+CpuInitFloatPointUnit PROC PUBLIC
+ ;
+ ; Initialize floating point units
+ ;
+ ; The following opcodes stand for instruction 'finit'
+ ; to be supported by some 64-bit assemblers
+ ;
+ DB 9Bh, 0DBh, 0E3h
+ fldcw mFpuControlWord
+
+ ;
+ ; Set OSFXSR bit 9 in CR4
+ ;
+ mov rax, cr4
+ or rax, 200h
+ mov cr4, rax
+
+ ldmxcsr mMmxControlWord
+ ret
+CpuInitFloatPointUnit ENDP
+
+CpuDisableInterrupt PROC PUBLIC
+
+ cli
+ ret
+
+CpuDisableInterrupt ENDP
+
+CpuEnableInterrupt PROC PUBLIC
+
+ sti
+ ret
+
+CpuEnableInterrupt ENDP
+
+MAX_NR_BUS EQU 0FFh
+CSR_DESIRED_CORES EQU 080h ; CSR D0:F0:R80
+
+GetCsrDesiredCores PROC PUBLIC
+
+ push rbx
+
+ ;
+ ; get Bus number from CPUID[1] EBX[31:24]
+ ;
+ mov eax, 1 ; bus 0
+ cpuid
+ bswap ebx
+ shr bl, 4
+ movzx eax, bl
+ ;
+ ; Compute CPU Bus Num
+ ; Bus Num = (MAX_NB_BUS - socket ID)
+ ;
+ xor eax, MAX_NR_BUS ; bus number = MAX_NR_BUS - socket ID
+ ;
+ ; eax = bus number
+ ; out 0CF8h, GQ1_CR_PCIEXBAR OR (Bus Num shl 16)
+ ;
+ or eax, 8000h
+ shl eax, 16
+ or eax, CSR_DESIRED_CORES ; D0:F1:R80h
+ mov dx, 0CF8h
+ out dx, eax
+ mov dx, 0CFCh
+ in eax, dx
+
+ pop rbx
+
+ ret
+
+GetCsrDesiredCores ENDP
+
+SetLockCsrDesiredCores PROC PUBLIC
+
+ push rbx
+
+ ;
+ ; get Bus number from CPUID[1] EBX[31:24]
+ ;
+ mov eax, 1 ; bus 0
+ cpuid
+ bswap ebx
+ shr bl, 4
+ movzx eax, bl
+ ;
+ ; Compute CPU Bus Num
+ ; Bus Num = (MAX_NB_BUS - socket ID)
+ ;
+ xor eax, MAX_NR_BUS ; bus number = MAX_NR_BUS - socket ID
+ ;
+ ; eax = bus number
+ ; out 0CF8h, GQ1_CR_PCIEXBAR OR (Bus Num shl 16)
+ ;
+ or eax, 8000h
+ shl eax, 16
+ or eax, CSR_DESIRED_CORES ; D0:F1:R80h
+ mov dx, 0CF8h
+ out dx, eax
+ mov dx, 0CFCh
+ in eax, dx
+ or eax, 10000h ; Bit[16] = Lock
+ out dx, eax
+
+ pop rbx
+ ret
+
+SetLockCsrDesiredCores ENDP
+
+;------------------------------------------------------------------------------
+; UINTN
+; CpuFlushTlb (
+; VOID
+; )
+;------------------------------------------------------------------------------
+CpuFlushTlb PROC PUBLIC
+ mov rax, cr3
+ mov cr3, rax
+ ret
+CpuFlushTlb ENDP
+
+;------------------------------------------------------------------------------
+; UINT16
+; CpuCodeSegment (
+; VOID
+; );
+;------------------------------------------------------------------------------
+CpuCodeSegment PROC PUBLIC
+ xor eax, eax
+ mov eax, cs
+ ret
+CpuCodeSegment ENDP
+
+;------------------------------------------------------------------------------
+; VOID
+; CpuLoadGlobalDescriptorTable (
+; VOID *Table16ByteAligned
+; );
+;------------------------------------------------------------------------------
+CpuLoadGlobalDescriptorTable PROC PUBLIC
+ lgdt FWORD PTR [rcx]
+ ret
+CpuLoadGlobalDescriptorTable ENDP
+
+;------------------------------------------------------------------------------
+; VOID
+; CpuLoadInterruptDescriptorTable (
+; VOID *Table16ByteAligned
+; );
+;------------------------------------------------------------------------------
+CpuLoadInterruptDescriptorTable PROC PUBLIC
+ lidt FWORD PTR [rcx]
+ ret
+CpuLoadInterruptDescriptorTable ENDP
+
+
+text ENDS
+END
+
+
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/x64/CpuLib.h b/ReferenceCode/Haswell/CpuInit/Dxe/x64/CpuLib.h
new file mode 100644
index 0000000..14699c1
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/x64/CpuLib.h
@@ -0,0 +1,168 @@
+/** @file
+ Library functions that can be called in both PEI and DXE phase
+
+@copyright
+ Copyright (c) 2004 - 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 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
+**/
+#ifndef _CPU_LIB_H_
+#define _CPU_LIB_H_
+
+#if 0
+UINTN
+CpuReadCr0 (
+ VOID
+ )
+/**
+@brief
+ Get CR0 value
+
+ @param[in] None
+
+ @retval CR0 value
+**/
+;
+
+VOID
+CpuWriteCr0 (
+ UINTN Value
+ )
+/**
+@brief
+ Write CR0 register
+
+ @param[in] Value - Value that will be written into CR0 register
+**/
+;
+
+UINTN
+CpuReadCr3 (
+ VOID
+ )
+/**
+@brief
+ Get CR3 register value
+
+ @param[in] None
+
+ @retval CR3 register value
+**/
+;
+
+VOID
+CpuWriteCr3 (
+ UINTN Value
+ )
+/**
+@brief
+ Write CR3 register
+
+ @param[in] Value - Value that will be written to CR3 register
+**/
+;
+
+UINTN
+CpuSetPower2 (
+ IN UINTN Input
+ )
+/**
+@brief
+ Calculate the power 2 value from the Input value
+
+ @param[in] Input - The number that will be calculated
+
+ @retval Power 2 value after calculated
+**/
+;
+
+UINT64
+CpuReadTsc (
+ VOID
+ )
+/**
+@brief
+ Read CPU TSC value
+
+ @param[in] None
+
+ @retval TSC value
+**/
+;
+
+VOID
+CpuBreak (
+ VOID
+ )
+/**
+@brief
+ Break by INT3
+
+ @param[in] None
+**/
+;
+
+VOID
+CpuInitSelectors (
+ VOID
+ )
+/**
+@brief
+ Initialize selectors by calling INT 68
+
+ @param[in] None
+**/
+;
+
+#endif
+
+UINT16
+CpuCodeSegment (
+ VOID
+ )
+/**
+@brief
+ Return code segment address - CS
+
+ @param[in] None
+
+ @retval Code segment address
+**/
+;
+
+VOID
+CpuLoadGlobalDescriptorTable (
+ VOID *Table16ByteAligned
+ )
+/**
+@brief
+ Get current GDT descriptor
+
+ @param[in] Table16ByteAligned - the table buffer that will store current GDT table descriptor
+**/
+;
+
+VOID
+CpuLoadInterruptDescriptorTable (
+ VOID *Table16ByteAligned
+ )
+/**
+@brief
+ Get current IDT descriptor
+
+ @param[in] Table16ByteAligned - the table buffer that will store current GDT table descriptor
+**/
+;
+
+#endif
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/x64/Exception.c b/ReferenceCode/Haswell/CpuInit/Dxe/x64/Exception.c
new file mode 100644
index 0000000..bcd306b
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/x64/Exception.c
@@ -0,0 +1,372 @@
+/** @file
+ EM64T Exception Handler
+
+@copyright
+ Copyright (c) 2006 - 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 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
+
+**/
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "CpuInitDxe.h"
+#include "MpCommon.h"
+#include "Exception.h"
+#endif
+
+typedef
+VOID
+(*EFI_INSTALL_EXCEPTION)(
+ IN UINT32 InterruptType,
+ IN VOID *SystemContext
+ );
+
+typedef struct {
+ UINT32 ErrorMessage;
+ UINT8 Interrupt;
+} EFI_EXCEPTION_HANDLER;
+
+///
+/// Error code flag indicating whether or not an error code will be
+/// pushed on the stack if an exception occurs.
+///
+/// 1 means an error code will be pushed, otherwise 0
+///
+/// bit 0 - exception 0
+/// bit 1 - exception 1
+/// etc.
+///
+UINT32 mErrorCodeFlag = 0x00027d00;
+
+///
+/// Local Table
+///
+EFI_EXCEPTION_HANDLER mExceptionTable[] = {
+ {
+ EFI_SW_EC_IA32_DIVIDE_ERROR,
+ INTERRUPT_HANDLER_DIVIDE_ZERO
+ },
+ {
+ EFI_SW_EC_IA32_DEBUG,
+ INTERRUPT_HANDLER_DEBUG
+ },
+ {
+ EFI_SW_EC_IA32_NMI,
+ INTERRUPT_HANDLER_NMI
+ },
+ {
+ EFI_SW_EC_IA32_BREAKPOINT,
+ INTERRUPT_HANDLER_BREAKPOINT
+ },
+ {
+ EFI_SW_EC_IA32_OVERFLOW,
+ INTERRUPT_HANDLER_OVERFLOW
+ },
+ {
+ EFI_SW_EC_IA32_BOUND,
+ INTERRUPT_HANDLER_BOUND
+ },
+ {
+ EFI_SW_EC_IA32_INVALID_OPCODE,
+ INTERRUPT_HANDLER_INVALID_OPCODE
+ },
+ ///
+ /// Interrupt 7, 9, 15 not defined in the debug support protocol. Hence no status codes for them!
+ ///
+ {
+ EFI_SW_EC_IA32_DOUBLE_FAULT,
+ INTERRUPT_HANDLER_DOUBLE_FAULT
+ },
+ {
+ EFI_SW_EC_IA32_INVALID_TSS,
+ INTERRUPT_HANDLER_INVALID_TSS
+ },
+ {
+ EFI_SW_EC_IA32_SEG_NOT_PRESENT,
+ INTERRUPT_HANDLER_SEGMENT_NOT_PRESENT
+ },
+ {
+ EFI_SW_EC_IA32_STACK_FAULT,
+ INTERRUPT_HANDLER_STACK_SEGMENT_FAULT
+ },
+ {
+ EFI_SW_EC_IA32_GP_FAULT,
+ INTERRUPT_HANDLER_GP_FAULT
+ },
+ {
+ EFI_SW_EC_IA32_PAGE_FAULT,
+ INTERRUPT_HANDLER_PAGE_FAULT
+ },
+ {
+ EFI_SW_EC_IA32_FP_ERROR,
+ INTERRUPT_HANDLER_MATH_FAULT
+ },
+ {
+ EFI_SW_EC_IA32_ALIGNMENT_CHECK,
+ INTERRUPT_HANDLER_ALIGNMENT_FAULT
+ },
+ {
+ EFI_SW_EC_IA32_MACHINE_CHECK,
+ INTERRUPT_HANDLER_MACHINE_CHECK
+ },
+ {
+ EFI_SW_EC_IA32_SIMD,
+ INTERRUPT_HANDLER_STREAMING_SIMD
+ }
+};
+
+UINTN mExceptionNumber = sizeof (mExceptionTable) / sizeof (EFI_EXCEPTION_HANDLER);
+
+CPU_STATUS_CODE_TEMPLATE mStatusCodeData = {
+ {
+ sizeof (EFI_STATUS_CODE_DATA),
+ sizeof (EFI_SYSTEM_CONTEXT_X64),
+ EFI_STATUS_CODE_DATA_TYPE_EXCEPTION_HANDLER_GUID
+ },
+ {
+ 0
+ }
+};
+
+UINT8 mExceptionLock = 0;
+
+/**
+ Report StatusCode for Exception
+
+ @param[in] InterruptType - Interrupt type
+ @param[in] SystemContext - EFI_SYSTEM_CONTEXT
+
+ @retval EFI_SUCCESS
+**/
+EFI_STATUS
+ReportData (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ UINT32 ErrorMessage;
+ UINT32 Index;
+
+ CopyMem (
+ &mStatusCodeData.SystemContext.SystemContextX64,
+ SystemContext.SystemContextX64,
+ sizeof (EFI_SYSTEM_CONTEXT_X64)
+ );
+
+ ErrorMessage = EFI_SOFTWARE_DXE_BS_DRIVER;
+ for (Index = 0; Index < mExceptionNumber; Index++) {
+ if (mExceptionTable[Index].Interrupt == InterruptType) {
+ ErrorMessage |= mExceptionTable[Index].ErrorMessage;
+ break;
+ }
+ }
+
+ ReportStatusCode (
+ (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED),
+ EFI_SOFTWARE_UNSPECIFIED | ErrorMessage
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Common exception handler
+
+ @param[in] InterruptType - Exception type
+ @param[in] SystemContext - EFI_SYSTEM_CONTEXT
+**/
+VOID
+EFIAPI
+CommonExceptionHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ AsmAcquireMPLock (&mExceptionLock);
+
+ DEBUG (
+ (EFI_D_ERROR,
+ "!!!! X64 Exception Type - %016lx CPU Apic ID - %08x!!!!\n",
+ InterruptType,
+ GetApicID (NULL,
+ NULL))
+ );
+ DEBUG (
+ (EFI_D_ERROR,
+ "RIP - %016lx, CS - %016lx, RFLAGS - %016lx\n",
+ SystemContext.SystemContextX64->Rip,
+ SystemContext.SystemContextX64->Cs,
+ SystemContext.SystemContextX64->Rflags)
+ );
+ if (mErrorCodeFlag & (1 << InterruptType)) {
+ DEBUG (
+ (EFI_D_ERROR,
+ "ExceptionData - %016lx\n",
+ SystemContext.SystemContextX64->ExceptionData)
+ );
+ }
+
+ DEBUG (
+ (EFI_D_ERROR,
+ "RAX - %016lx, RCX - %016lx, RDX - %016lx\n",
+ SystemContext.SystemContextX64->Rax,
+ SystemContext.SystemContextX64->Rcx,
+ SystemContext.SystemContextX64->Rdx)
+ );
+ DEBUG (
+ (EFI_D_ERROR,
+ "RBX - %016lx, RSP - %016lx, RBP - %016lx\n",
+ SystemContext.SystemContextX64->Rbx,
+ SystemContext.SystemContextX64->Rsp,
+ SystemContext.SystemContextX64->Rbp)
+ );
+ DEBUG (
+ (EFI_D_ERROR,
+ "RSI - %016lx, RDI - %016lx\n",
+ SystemContext.SystemContextX64->Rsi,
+ SystemContext.SystemContextX64->Rdi)
+ );
+ DEBUG (
+ (EFI_D_ERROR,
+ "R8 - %016lx, R9 - %016lx, R10 - %016lx\n",
+ SystemContext.SystemContextX64->R8,
+ SystemContext.SystemContextX64->R9,
+ SystemContext.SystemContextX64->R10)
+ );
+ DEBUG (
+ (EFI_D_ERROR,
+ "R11 - %016lx, R12 - %016lx, R13 - %016lx\n",
+ SystemContext.SystemContextX64->R11,
+ SystemContext.SystemContextX64->R12,
+ SystemContext.SystemContextX64->R13)
+ );
+ DEBUG (
+ (EFI_D_ERROR,
+ "R14 - %016lx, R15 - %016lx\n",
+ SystemContext.SystemContextX64->R14,
+ SystemContext.SystemContextX64->R15)
+ );
+ DEBUG (
+ (EFI_D_ERROR,
+ "DS - %016lx, ES - %016lx, FS - %016lx\n",
+ SystemContext.SystemContextX64->Ds,
+ SystemContext.SystemContextX64->Es,
+ SystemContext.SystemContextX64->Fs)
+ );
+ DEBUG (
+ (EFI_D_ERROR,
+ "GS - %016lx, SS - %016lx\n",
+ SystemContext.SystemContextX64->Gs,
+ SystemContext.SystemContextX64->Ss)
+ );
+ DEBUG (
+ (EFI_D_ERROR,
+ "GDTR - %016lx %016lx, LDTR - %016lx\n",
+ SystemContext.SystemContextX64->Gdtr[0],
+ SystemContext.SystemContextX64->Gdtr[1],
+ SystemContext.SystemContextX64->Ldtr)
+ );
+ DEBUG (
+ (EFI_D_ERROR,
+ "IDTR - %016lx %016lx, TR - %016lx\n",
+ SystemContext.SystemContextX64->Idtr[0],
+ SystemContext.SystemContextX64->Idtr[1],
+ SystemContext.SystemContextX64->Tr)
+ );
+ DEBUG (
+ (EFI_D_ERROR,
+ "CR0 - %016lx, CR2 - %016lx, CR3 - %016lx\n",
+ SystemContext.SystemContextX64->Cr0,
+ SystemContext.SystemContextX64->Cr2,
+ SystemContext.SystemContextX64->Cr3)
+ );
+ DEBUG (
+ (EFI_D_ERROR,
+ "CR4 - %016lx, CR8 - %016lx\n",
+ SystemContext.SystemContextX64->Cr4,
+ SystemContext.SystemContextX64->Cr8)
+ );
+ DEBUG (
+ (EFI_D_ERROR,
+ "DR0 - %016lx, DR1 - %016lx, DR2 - %016lx\n",
+ SystemContext.SystemContextX64->Dr0,
+ SystemContext.SystemContextX64->Dr1,
+ SystemContext.SystemContextX64->Dr2)
+ );
+ DEBUG (
+ (EFI_D_ERROR,
+ "DR3 - %016lx, DR6 - %016lx, DR7 - %016lx\n",
+ SystemContext.SystemContextX64->Dr3,
+ SystemContext.SystemContextX64->Dr6,
+ SystemContext.SystemContextX64->Dr7)
+ );
+
+ ///
+ /// Report Status Code
+ ///
+ ReportData (InterruptType, SystemContext);
+ AsmReleaseMPLock (&mExceptionLock);
+
+ ///
+ /// Use this macro to hang so that the compiler does not optimize out
+ /// the following RET instructions. This allows us to return if we
+ /// have a debugger attached.
+ ///
+ EFI_DEADLOOP ();
+
+ return;
+}
+
+/**
+ Install the IA-32 EM64T Exception Handler.
+ The current operation (which likely will change) will uninstall all the
+ pertinent exception handlers (0-7, 10-14, 16-19) except for Int8 which the timer
+ is currently sitting on (or soon will be).
+
+ It then installs all the appropriate handlers for each exception.
+
+ The handler then calls gRT->ReportStatusCode with a specific progress code. The
+ progress codes for now start at 0x200 for IA-32 processors. See Status Code
+ Specification for details. The Status code Specification uses the enumeration from
+ the EFI 1.1 Debug Support Protocol.
+
+ @param[in] CpuProtocol - Instance of CPU Arch Protocol
+
+ @retval EFI_SUCCESS - This function always return success after registering handlers.
+**/
+EFI_STATUS
+InitializeException (
+ IN EFI_CPU_ARCH_PROTOCOL *CpuProtocol
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+
+ CpuProtocol->DisableInterrupt (CpuProtocol);
+
+ for (Index = 0; Index < mExceptionNumber; Index++) {
+ Status = CpuProtocol->RegisterInterruptHandler (CpuProtocol, mExceptionTable[Index].Interrupt, NULL);
+ ///
+ /// Add in our handler
+ ///
+ Status = CpuProtocol->RegisterInterruptHandler (
+ CpuProtocol,
+ mExceptionTable[Index].Interrupt,
+ CommonExceptionHandler
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/x64/MemoryOperation.c b/ReferenceCode/Haswell/CpuInit/Dxe/x64/MemoryOperation.c
new file mode 100644
index 0000000..5fae506
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/x64/MemoryOperation.c
@@ -0,0 +1,729 @@
+/** @file
+ Memory Operation Functions for IA32 Architecture.
+
+@copyright
+ Copyright (c) 2006 - 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 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
+
+**/
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "CpuInitDxe.h"
+#include "CpuLib.h"
+#include "MpCommon.h"
+#include "VirtualMemory.h"
+#include "MemoryAttribute.h"
+#endif
+
+VOID
+InitializeExternalVectorTablePtr (
+ EFI_CPU_INTERRUPT_HANDLER *VectorTable
+ );
+
+extern EFI_CPU_INTERRUPT_HANDLER mExternalVectorTable[];
+extern EFI_PHYSICAL_ADDRESS mBackupBuffer;
+
+UINT8 *mPageStore = NULL;
+UINTN mPageStoreSize = 16;
+UINTN mPageStoreIndex = 0;
+
+UINT64 mValidMtrrAddressMask;
+UINT64 mValidMtrrBitsMask;
+
+///
+/// BugBug: Non Portable
+///
+#if defined (__GNUC__)
+#define ALIGN_16BYTE_BOUNDRY __attribute__ ((aligned (16)))
+#else
+#define ALIGN_16BYTE_BOUNDRY __declspec (align (16))
+#endif
+
+#pragma pack(1)
+typedef struct {
+ UINT16 LimitLow;
+ UINT16 BaseLow;
+ UINT8 BaseMiddle;
+ UINT8 Attributes1;
+ UINT8 Attributes2;
+ UINT8 BaseHigh;
+} SEGMENT_DESCRIPTOR_x64;
+
+typedef struct {
+ UINT16 Limit;
+ UINTN Base;
+} PSEUDO_DESCRIPTOR_x64;
+
+#pragma pack()
+
+ALIGN_16BYTE_BOUNDRY SEGMENT_DESCRIPTOR_x64 gGdt[] = {
+ { /// NULL Selector: selector[0]
+ 0, /// limit 15:0
+ 0, /// base 15:0
+ 0, /// base 23:16
+ 0, ///
+ 0, /// type & limit 19:16
+ 0, /// base 31:24
+ /// 0, /// base 63:32
+ /// 0 /// reserved
+ ///
+ },
+ { /// Linear Selector: selector[8]
+ 0xffff, /// limit 15:0
+ 0, /// base 15:0
+ 0, /// base 23:16
+ 0x93, /// present, ring 0, data, expand-up writable
+ 0xcf, /// type & limit 19:16
+ 0, /// base 31:24
+ /// 0, /// base 63:32
+ /// 0 /// reserved
+ ///
+ },
+ { /// Linear code Selector: selector[10]
+ 0xffff, /// limit 15:0
+ 0, /// base 15:0
+ 0, /// base 23:16
+ 0x9b, /// present, ring 0, code, expand-up writable
+ 0xcf, /// type & limit 19:16
+ 0, /// base 31:24
+ /// 0, /// base 63:32
+ /// 0 /// reserved
+ ///
+ },
+ { /// Compatibility mode data Selector: selector[18]
+ 0xffff, /// limit 15:0
+ 0, /// base 15:0
+ 0, /// base 23:16
+ 0x93, /// type & limit 19:16
+ 0xcf,
+ 0, /// base 31:24
+ /// 0, /// base 63:32
+ /// 0 /// reserved
+ ///
+ },
+ { /// Compatibility code Selector: selector[20]
+ 0xffff, /// limit 15:0
+ 0, /// base 15:0
+ 0, /// base 23:16
+ 0x9b, /// type & limit 19:16
+ 0xcf,
+ 0, /// base 31:24
+ /// 0, /// base 63:32
+ /// 0 /// reserved
+ ///
+ },
+ { /// Spare3 Selector: selector[28]
+ 0, /// limit 15:0
+ 0, /// base 15:0
+ 0, /// base 23:16
+ 0, /// type & limit 19:16
+ 0, /// base 31:24
+ 0,
+ ///
+ /// 0, /// base 63:32
+ /// 0 /// reserved
+ ///
+ },
+ { /// 64-bit data Selector:selector[30]
+ 0xffff, /// limit 15:0
+ 0, /// base 15:0
+ 0, /// base 23:16
+ 0x93, /// type & limit 19:16
+ 0xcf,
+ 0, /// base 31:24
+ /// 0, /// base 63:32
+ /// 0 /// reserved
+ ///
+ },
+ { /// 64-bit code Selector: selector[38]
+ 0xffff, /// limit 15:0
+ 0, /// base 15:0
+ 0, /// base 23:16
+ 0x9b, /// type & limit 19:16
+ 0xaf,
+ 0, /// base 31:24
+ /// 0, /// base 63:32
+ /// 0 /// reserved
+ ///
+ },
+ { /// Spare3 Selector: selector[40]
+ 0, /// limit 15:0
+ 0, /// base 15:0
+ 0, /// base 23:16
+ 0, /// type & limit 19:16
+ 0, /// base 31:24
+ 0,
+ ///
+ /// 0, /// base 63:32
+ /// 0 /// reserved
+ ///
+ }
+};
+
+ALIGN_16BYTE_BOUNDRY PSEUDO_DESCRIPTOR_x64 gGdtPseudoDescriptor = {
+ sizeof (gGdt) - 1,
+ (UINTN) gGdt
+};
+
+INTERRUPT_GATE_DESCRIPTOR gIdtTable[INTERRUPT_VECTOR_NUMBER] = { 0 };
+
+ALIGN_16BYTE_BOUNDRY PSEUDO_DESCRIPTOR_x64 gLidtPseudoDescriptor = {
+ sizeof (gIdtTable) - 1,
+ (UINTN) gIdtTable
+};
+
+/**
+ Init Global Descriptor table
+**/
+VOID
+InitializeSelectors (
+ VOID
+ )
+{
+ CpuLoadGlobalDescriptorTable (&gGdtPseudoDescriptor);
+}
+
+/**
+ Generic IDT Vector Handlers for the Host
+**/
+VOID
+AsmIdtVector00 (
+ VOID
+ );
+
+/**
+ Initialize Interrupt descriptor Tables
+**/
+VOID
+InitializeInterruptTables (
+ VOID
+ )
+{
+ UINT16 CodeSegment;
+ INTERRUPT_GATE_DESCRIPTOR *IdtEntry;
+ UINT8 *CurrentHandler;
+ UINT32 Index;
+
+ CodeSegment = CpuCodeSegment ();
+
+ IdtEntry = gIdtTable;
+ CurrentHandler = (UINT8 *) (UINTN) AsmIdtVector00;
+ for (Index = 0; Index < INTERRUPT_VECTOR_NUMBER; Index++) {
+ IdtEntry[Index].Offset15To0 = (UINT16) (UINTN) CurrentHandler;
+ IdtEntry[Index].SegmentSelector = CodeSegment;
+ IdtEntry[Index].Attributes = INTERRUPT_GATE_ATTRIBUTE;
+ ///
+ /// 8e00;
+ ///
+ IdtEntry[Index].Offset31To16 = (UINT16) ((UINTN) CurrentHandler >> 16);
+ IdtEntry[Index].Offset63To32 = (UINT32) ((UINTN) CurrentHandler >> 32);
+
+ CurrentHandler += 0x8;
+ ///
+ }
+
+ CpuLoadInterruptDescriptorTable (&gLidtPseudoDescriptor);
+
+ return;
+}
+
+/**
+ Initialize cache attributes based on MTRR
+**/
+VOID
+InitailizeCacheAttributes (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS Page;
+ EFI_CPUID_REGISTER FeatureInfo;
+ EFI_CPUID_REGISTER FunctionInfo;
+ UINT8 PhysicalAddressBits;
+ UINT32 MsrNum;
+ UINT64 TempQword;
+ UINT64 ComplementBits;
+ UINT32 VariableMtrrLimit;
+
+ VariableMtrrLimit = (UINT32) (AsmReadMsr64 (IA32_MTRR_CAP) & B_IA32_MTRR_VARIABLE_SUPPORT);
+
+ ///
+ /// Allocate 16 pages
+ ///
+ Status = (gBS->AllocatePages)(AllocateAnyPages, EfiBootServicesData, mPageStoreSize, &Page);
+ ASSERT_EFI_ERROR (Status);
+
+ mPageStore = (UINT8 *) (UINTN) Page;
+
+ ZeroMem (mPageStore, 0x1000 * mPageStoreSize);
+
+ ///
+ /// Check returned value of Eax for extended CPUID functions
+ ///
+ AsmCpuid (
+ CPUID_EXTENDED_FUNCTION,
+ &FunctionInfo.RegEax,
+ &FunctionInfo.RegEbx,
+ &FunctionInfo.RegEcx,
+ &FunctionInfo.RegEdx
+ );
+
+ PhysicalAddressBits = 36;
+
+ ///
+ /// If CPU supports extended functions, get the Physical Address size by reading EAX[7:0]
+ ///
+ if (FunctionInfo.RegEax > CPUID_EXTENDED_FUNCTION) {
+ AsmCpuid (
+ CPUID_VIR_PHY_ADDRESS_SIZE,
+ &FeatureInfo.RegEax,
+ &FeatureInfo.RegEbx,
+ &FeatureInfo.RegEcx,
+ &FeatureInfo.RegEdx
+ );
+ PhysicalAddressBits = (UINT8) FeatureInfo.RegEax;
+ }
+
+ mValidMtrrBitsMask = (((UINT64) 1) << PhysicalAddressBits) - 1;
+ mValidMtrrAddressMask = mValidMtrrBitsMask & 0xfffffffffffff000;
+
+ ComplementBits = mValidMtrrBitsMask & 0xfffffff000000000;
+ if (ComplementBits != 0) {
+ ///
+ /// Disable cache and clear the corresponding MTRR bits
+ ///
+ PreMtrrChange ();
+ for (MsrNum = CACHE_VARIABLE_MTRR_BASE;
+ MsrNum < (CACHE_VARIABLE_MTRR_BASE + VariableMtrrLimit * 2 - 1);
+ MsrNum += 2
+ ) {
+ TempQword = AsmReadMsr64 (MsrNum + 1);
+ if ((TempQword & B_CACHE_MTRR_VALID) != 0) {
+ ///
+ /// MTRR Physical Mask
+ ///
+ TempQword = TempQword | ComplementBits;
+ AsmWriteMsr64 (MsrNum + 1, TempQword);
+ }
+ }
+
+ ///
+ /// Enable Cache and set the corresponding MTRR bits
+ ///
+ PostMtrrChange ();
+ }
+}
+
+/**
+ Allocate zeroed pages
+
+ @retval Pointer to the page buffer
+**/
+VOID *
+AllocateZeroedPage (
+ VOID
+ )
+{
+ if (mPageStoreIndex >= mPageStoreSize) {
+ ///
+ /// We are out of space
+ ///
+ return NULL;
+ }
+
+ return (VOID *) (UINTN) &mPageStore[0x1000 * mPageStoreIndex++];
+}
+
+/**
+ Convert 2MB page tables to 4KB page tables
+
+ @param[in] PageAddress - Page address to convert
+ @param[in] PageDirectoryToConvert - Page table that will be converted
+**/
+VOID
+Convert2MBPageTo4KPages (
+ IN EFI_PHYSICAL_ADDRESS PageAddress,
+ IN OUT x64_PAGE_TABLE_ENTRY **PageDirectoryToConvert
+ )
+{
+ UINTN Index;
+ EFI_PHYSICAL_ADDRESS WorkingAddress;
+ x64_PAGE_TABLE_ENTRY_4K *PageTableEntry;
+ x64_PAGE_TABLE_ENTRY Attributes;
+
+ ///
+ /// Save the attributes of the 2MB table
+ ///
+ Attributes.Page2Mb.Uint64 = (*PageDirectoryToConvert)->Page2Mb.Uint64;
+
+ ///
+ /// Convert PageDirectoryEntry2MB into a 4K Page Directory
+ ///
+ PageTableEntry = AllocateZeroedPage ();
+ if (PageTableEntry == NULL) {
+ return;
+ }
+ (*PageDirectoryToConvert)->Page2Mb.Uint64 = (UINT64) PageTableEntry;
+ (*PageDirectoryToConvert)->Page2Mb.Bits.ReadWrite = 1;
+ (*PageDirectoryToConvert)->Page2Mb.Bits.Present = 1;
+
+ WorkingAddress = PageAddress;
+ for (Index = 0; Index < 512; Index++, PageTableEntry++, WorkingAddress += 0x1000) {
+ PageTableEntry->Uint64 = (UINT64) WorkingAddress;
+ PageTableEntry->Bits.Present = 1;
+
+ ///
+ /// Update the new page to have the same attributes as the 2MB page
+ ///
+ PageTableEntry->Bits.ReadWrite = Attributes.Common.ReadWrite;
+ PageTableEntry->Bits.CacheDisabled = Attributes.Common.CacheDisabled;
+ PageTableEntry->Bits.WriteThrough = Attributes.Common.WriteThrough;
+
+ if (WorkingAddress == PageAddress) {
+ ///
+ /// Return back the 4K page that matches the Working addresss
+ ///
+ *PageDirectoryToConvert = (x64_PAGE_TABLE_ENTRY *) PageTableEntry;
+ }
+ }
+}
+
+/**
+ Get current memory mapping information
+
+ @param[in] BaseAddress - get current memory mapping by this Base address
+ @param[in] PageTable - page table that translated this base address
+ @param[in] Page2MBytes - TRUE if this is 2MBytes page table
+
+ @retval EFI_NOT_FOUND - page table not found
+ @retval EFI_SUCCESS - page table found
+**/
+EFI_STATUS
+GetCurrentMapping (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ OUT x64_PAGE_TABLE_ENTRY **PageTable,
+ OUT BOOLEAN *Page2MBytes
+ )
+{
+ UINT64 Cr3;
+ x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageMapLevel4Entry;
+ x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageDirectoryPointerEntry;
+ x64_PAGE_TABLE_ENTRY_2M *PageTableEntry2Mb;
+ x64_PAGE_DIRECTORY_ENTRY_4K *PageDirectoryEntry4k;
+ x64_PAGE_TABLE_ENTRY_4K *PageTableEntry4k;
+ UINTN Pml4Index;
+ UINTN PdpIndex;
+ UINTN Pde2MbIndex;
+ UINTN PteIndex;
+
+ Cr3 = AsmReadCr3 ();
+
+ PageMapLevel4Entry = (x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *) (Cr3 & 0x000ffffffffff000);
+
+ Pml4Index = (UINTN) RShiftU64 (BaseAddress, 39) & 0x1ff;
+ if (PageMapLevel4Entry[Pml4Index].Bits.Present == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ PageDirectoryPointerEntry = (x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *) (PageMapLevel4Entry[Pml4Index].Uint64 & 0x000ffffffffff000);
+ PdpIndex = (UINTN) RShiftU64 (BaseAddress, 30) & 0x1ff;
+ if (PageDirectoryPointerEntry[PdpIndex].Bits.Present == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ PageTableEntry2Mb = (x64_PAGE_TABLE_ENTRY_2M *) (PageDirectoryPointerEntry[PdpIndex].Uint64 & 0x000ffffffffff000);
+ Pde2MbIndex = (UINTN) RShiftU64 (BaseAddress, 21) & 0x1ff;
+ if (PageTableEntry2Mb[Pde2MbIndex].Bits.Present == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (PageTableEntry2Mb[Pde2MbIndex].Bits.MustBe1 == 1) {
+ ///
+ /// We found a 2MByte page so lets return it
+ ///
+ *Page2MBytes = TRUE;
+ *PageTable = (x64_PAGE_TABLE_ENTRY *) &PageTableEntry2Mb[Pde2MbIndex].Uint64;
+ return EFI_SUCCESS;
+ }
+
+ ///
+ /// 4K page so keep walking
+ ///
+ PageDirectoryEntry4k = (x64_PAGE_DIRECTORY_ENTRY_4K *) &PageTableEntry2Mb[Pde2MbIndex].Uint64;
+
+ PageTableEntry4k = (x64_PAGE_TABLE_ENTRY_4K *) (PageDirectoryEntry4k[Pde2MbIndex].Uint64 & 0x000ffffffffff000);
+ PteIndex = (UINTN) RShiftU64 (BaseAddress, 12) & 0x1ff;
+ if (PageTableEntry4k[PteIndex].Bits.Present == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ *Page2MBytes = FALSE;
+ *PageTable = (x64_PAGE_TABLE_ENTRY *) &PageTableEntry4k[PteIndex];
+ return EFI_SUCCESS;
+}
+
+/**
+ Prepare memory for essential system tables.
+
+ @retval EFI_SUCCESS - Memory successfully prepared.
+**/
+EFI_STATUS
+PrepareMemory (
+ VOID
+ )
+{
+ ///
+ /// Allocate space to convert 2MB page tables to 4K tables.
+ /// This can not be done at call time as the TPL level will
+ /// not be correct.
+ ///
+ InitailizeCacheAttributes ();
+
+ InitializeExternalVectorTablePtr (mExternalVectorTable);
+ ///
+ /// Initialize the Interrupt Descriptor Table
+ ///
+ InitializeInterruptTables ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Prepare Wakeup Buffer and stack for APs.
+
+ @param[in] WakeUpBuffer - Pointer to the address of wakeup buffer for output.
+ @param[in] StackAddressStart - Pointer to the stack address of APs for output.
+ @param[in] MaximumCPUsForThisSystem - Maximum CPUs in this system.
+
+ @retval EFI_SUCCESS - Memory successfully prepared for APs.
+ @retval Other - Error occurred while allocating memory.
+**/
+EFI_STATUS
+PrepareMemoryForAPs (
+ OUT EFI_PHYSICAL_ADDRESS *WakeUpBuffer,
+ OUT VOID **StackAddressStart,
+ IN UINTN MaximumCPUsForThisSystem
+ )
+{
+ EFI_STATUS Status;
+ MP_ASSEMBLY_ADDRESS_MAP AddressMap;
+
+ ///
+ /// Release All APs with a lock and wait for them to retire to rendezvous procedure.
+ /// We need a page (4KB) of memory for IA-32 to use broadcast APIs, on a temporary basis.
+ ///
+ Status = AllocateWakeUpBuffer (WakeUpBuffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ///
+ /// Claim memory for AP stack
+ ///
+ Status = AllocateReservedMemoryBelow4G (
+ MaximumCPUsForThisSystem * STACK_SIZE_PER_PROC,
+ StackAddressStart
+ );
+
+ if (EFI_ERROR (Status)) {
+ (gBS->FreePages)(*WakeUpBuffer, 1);
+ return Status;
+ }
+
+ AsmGetAddressMap (&AddressMap);
+ CopyMem ((VOID *) (UINTN) *WakeUpBuffer, AddressMap.RendezvousFunnelAddress, AddressMap.Size);
+ *(UINT32 *) (UINTN) (*WakeUpBuffer + AddressMap.FlatJumpOffset + 3) = (UINT32) (*WakeUpBuffer + AddressMap.PModeEntryOffset);
+ *(UINT32 *) (UINTN) (*WakeUpBuffer + AddressMap.LongJumpOffset + 2) = (UINT32) (*WakeUpBuffer + AddressMap.LModeEntryOffset);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Prepare exchange information for APs.
+
+ @param[in] ExchangeInfo - Pointer to the exchange info buffer for output.
+ @param[in] StackAddressStart - Start address of APs' stacks.
+ @param[in] ApFunction - Address of function assigned to AP.
+ @param[in] WakeUpBuffer - Pointer to the address of wakeup buffer.
+
+ @retval EFI_SUCCESS - Exchange Info successfully prepared for APs.
+**/
+EFI_STATUS
+PrepareExchangeInfo (
+ OUT MP_CPU_EXCHANGE_INFO *ExchangeInfo,
+ IN VOID *StackAddressStart,
+ IN VOID *ApFunction,
+ IN EFI_PHYSICAL_ADDRESS WakeUpBuffer
+ )
+{
+ ZeroMem ((VOID *) ExchangeInfo, EFI_PAGE_SIZE - MP_CPU_EXCHANGE_INFO_OFFSET);
+
+ ExchangeInfo->Lock = VacantFlag;
+ ExchangeInfo->StackStart = StackAddressStart;
+ ExchangeInfo->StackSize = STACK_SIZE_PER_PROC;
+ ExchangeInfo->ApFunction = ApFunction;
+
+ CopyMem (
+ (VOID *) (UINTN) &ExchangeInfo->GdtrProfile,
+ (VOID *) (UINTN) mAcpiCpuData->GdtrProfile,
+ sizeof (PSEUDO_DESCRIPTOR)
+ );
+ CopyMem (
+ (VOID *) (UINTN) &ExchangeInfo->IdtrProfile,
+ (VOID *) (UINTN) mAcpiCpuData->IdtrProfile,
+ sizeof (PSEUDO_DESCRIPTOR)
+ );
+
+ ExchangeInfo->BufferStart = (UINT32) WakeUpBuffer;
+ ExchangeInfo->Cr3 = (UINT32) (AsmReadCr3 ());
+ ExchangeInfo->InitFlag = 1;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Prepare Wakeup Buffer and stack for APs.
+
+ @param[in] WakeUpBuffer - Pointer to the address of wakeup buffer for output.
+ @param[in] StackAddressStart - Pointer to the stack address of APs for output.
+
+ @retval EFI_SUCCESS - Memory successfully prepared for APs.
+**/
+EFI_STATUS
+S3PrepareMemoryForAPs (
+ OUT EFI_PHYSICAL_ADDRESS *WakeUpBuffer,
+ OUT VOID **StackAddressStart
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Prepare exchange information for APs.
+
+ @param[in] ExchangeInfo - Pointer to the exchange info for output.
+ @param[in] StackAddressStart - Start address of APs' stacks.
+ @param[in] ApFunction - Address of function assigned to AP.
+ @param[in] WakeUpBuffer - Pointer to the address of wakeup buffer.
+
+ @retval EFI_SUCCESS - Exchange Info successfully prepared for APs.
+**/
+EFI_STATUS
+S3PrepareExchangeInfo (
+ OUT MP_CPU_EXCHANGE_INFO *ExchangeInfo,
+ IN VOID *StackAddressStart,
+ IN VOID *ApFunction,
+ IN EFI_PHYSICAL_ADDRESS WakeUpBuffer
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Dynamically write the far jump destination in APs' wakeup buffer,
+ in order to refresh APs' CS registers for mode switching.
+**/
+VOID
+RedirectFarJump (
+ VOID
+ )
+{
+ MP_ASSEMBLY_ADDRESS_MAP AddressMap;
+
+ AsmGetAddressMap (&AddressMap);
+ *(UINT32 *) (UINTN) (mAcpiCpuData->WakeUpBuffer + AddressMap.FlatJumpOffset + 3) = (UINT32) (mAcpiCpuData->WakeUpBuffer + AddressMap.PModeEntryOffset);
+ *(UINT32 *) (UINTN) (mAcpiCpuData->WakeUpBuffer + AddressMap.LongJumpOffset + 2) = (UINT32) (mAcpiCpuData->WakeUpBuffer + AddressMap.LModeEntryOffset);
+
+ return;
+}
+
+/**
+ Prepare GDTR and IDTR for AP
+
+ @param[in] Gdtr - The GDTR profile
+ @param[in] Idtr - The IDTR profile
+
+ @retval EFI_STATUS - status returned by each sub-routine
+ @retval EFI_SUCCESS - GDTR and IDTR has been prepared for AP
+**/
+EFI_STATUS
+PrepareGdtIdtForAP (
+ OUT PSEUDO_DESCRIPTOR *Gdtr,
+ OUT PSEUDO_DESCRIPTOR *Idtr
+ )
+{
+ INTERRUPT_GATE_DESCRIPTOR *IdtForAP;
+ SEGMENT_DESCRIPTOR *GdtForAP;
+
+ PSEUDO_DESCRIPTOR *IdtrForBSP;
+ PSEUDO_DESCRIPTOR *GdtrForBSP;
+
+ UINT16 *MceHandler;
+ EFI_STATUS Status;
+
+ AsmGetGdtrIdtr (&GdtrForBSP, &IdtrForBSP);
+
+ ///
+ /// Allocate reserved memory for IDT
+ ///
+ Status = AllocateAlignedReservedMemory (
+ IdtrForBSP->Limit + 1,
+ 8,
+ (VOID **) &IdtForAP
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ///
+ /// Allocate reserved memory for GDT
+ ///
+ Status = AllocateAlignedReservedMemory (
+ GdtrForBSP->Limit + 1,
+ 8,
+ (VOID **) &GdtForAP
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = (gBS->AllocatePool)(EfiReservedMemoryType, SIZE_OF_MCE_HANDLER, (VOID **) &MceHandler);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ///
+ /// McheHandler content: iret (opcode = 0xcf)
+ ///
+ *MceHandler = 0xCF48;
+
+ CopyMem (GdtForAP, (VOID *) GdtrForBSP->Base, GdtrForBSP->Limit + 1);
+ CopyMem (IdtForAP, (VOID *) IdtrForBSP->Base, IdtrForBSP->Limit + 1);
+
+ IdtForAP[INTERRUPT_HANDLER_MACHINE_CHECK].Offset15To0 = (UINT16) (UINTN) MceHandler;
+ IdtForAP[INTERRUPT_HANDLER_MACHINE_CHECK].Offset31To16 = (UINT16) ((UINTN) MceHandler >> 16);
+ IdtForAP[INTERRUPT_HANDLER_MACHINE_CHECK].Offset63To32 = (UINT32) ((UINTN) MceHandler >> 32);
+
+ ///
+ /// Create Gdtr, IDTR profile
+ ///
+ Gdtr->Base = (UINTN) GdtForAP;
+ Gdtr->Limit = GdtrForBSP->Limit;
+
+ Idtr->Base = (UINTN) IdtForAP;
+ Idtr->Limit = IdtrForBSP->Limit;
+
+ return EFI_SUCCESS;
+}
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/x64/MemoryOperationDbgr.c b/ReferenceCode/Haswell/CpuInit/Dxe/x64/MemoryOperationDbgr.c
new file mode 100644
index 0000000..329a4a5
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/x64/MemoryOperationDbgr.c
@@ -0,0 +1,749 @@
+/** @file
+ Memory Operation Functions for IA32 Architecture.
+
+@copyright
+ Copyright (c) 2006 - 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 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
+
+**/
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "CpuInitDxeDbgr.h"
+#include "CpuLib.h"
+#include "MpCommon.h"
+#include "VirtualMemory.h"
+#include "MemoryAttribute.h"
+#endif
+
+//(AMI_CHG+)>
+#if defined(AMI_PEI_DEBUG_SUPPORT) && AMI_PEI_DEBUG_SUPPORT
+extern AMI_DEBUGGER_CPU_PROTOCOL *mAmiDebuggerCpuProtocol;
+#endif
+//<(AMI_CHG+)
+
+VOID
+InitializeExternalVectorTablePtr (
+ EFI_CPU_INTERRUPT_HANDLER *VectorTable
+ );
+
+extern EFI_CPU_INTERRUPT_HANDLER mExternalVectorTable[];
+extern EFI_PHYSICAL_ADDRESS mBackupBuffer;
+
+UINT8 *mPageStore = NULL;
+UINTN mPageStoreSize = 16;
+UINTN mPageStoreIndex = 0;
+
+UINT64 mValidMtrrAddressMask;
+UINT64 mValidMtrrBitsMask;
+
+///
+/// BugBug: Non Portable
+///
+#if defined (__GNUC__)
+#define ALIGN_16BYTE_BOUNDRY __attribute__ ((aligned (16)))
+#else
+#define ALIGN_16BYTE_BOUNDRY __declspec (align (16))
+#endif
+
+#pragma pack(1)
+typedef struct {
+ UINT16 LimitLow;
+ UINT16 BaseLow;
+ UINT8 BaseMiddle;
+ UINT8 Attributes1;
+ UINT8 Attributes2;
+ UINT8 BaseHigh;
+} SEGMENT_DESCRIPTOR_x64;
+
+typedef struct {
+ UINT16 Limit;
+ UINTN Base;
+} PSEUDO_DESCRIPTOR_x64;
+
+#pragma pack()
+
+ALIGN_16BYTE_BOUNDRY SEGMENT_DESCRIPTOR_x64 gGdt[] = {
+ { /// NULL Selector: selector[0]
+ 0, /// limit 15:0
+ 0, /// base 15:0
+ 0, /// base 23:16
+ 0, ///
+ 0, /// type & limit 19:16
+ 0, /// base 31:24
+ /// 0, /// base 63:32
+ /// 0 /// reserved
+ ///
+ },
+ { /// Linear Selector: selector[8]
+ 0xffff, /// limit 15:0
+ 0, /// base 15:0
+ 0, /// base 23:16
+ 0x93, /// present, ring 0, data, expand-up writable
+ 0xcf, /// type & limit 19:16
+ 0, /// base 31:24
+ /// 0, /// base 63:32
+ /// 0 /// reserved
+ ///
+ },
+ { /// Linear code Selector: selector[10]
+ 0xffff, /// limit 15:0
+ 0, /// base 15:0
+ 0, /// base 23:16
+ 0x9b, /// present, ring 0, code, expand-up writable
+ 0xcf, /// type & limit 19:16
+ 0, /// base 31:24
+ /// 0, /// base 63:32
+ /// 0 /// reserved
+ ///
+ },
+ { /// Compatibility mode data Selector: selector[18]
+ 0xffff, /// limit 15:0
+ 0, /// base 15:0
+ 0, /// base 23:16
+ 0x93, /// type & limit 19:16
+ 0xcf,
+ 0, /// base 31:24
+ /// 0, /// base 63:32
+ /// 0 /// reserved
+ ///
+ },
+ { /// Compatibility code Selector: selector[20]
+ 0xffff, /// limit 15:0
+ 0, /// base 15:0
+ 0, /// base 23:16
+ 0x9b, /// type & limit 19:16
+ 0xcf,
+ 0, /// base 31:24
+ /// 0, /// base 63:32
+ /// 0 /// reserved
+ ///
+ },
+ { /// Spare3 Selector: selector[28]
+ 0, /// limit 15:0
+ 0, /// base 15:0
+ 0, /// base 23:16
+ 0, /// type & limit 19:16
+ 0, /// base 31:24
+ 0,
+ ///
+ /// 0, /// base 63:32
+ /// 0 /// reserved
+ ///
+ },
+ { /// 64-bit data Selector:selector[30]
+ 0xffff, /// limit 15:0
+ 0, /// base 15:0
+ 0, /// base 23:16
+ 0x93, /// type & limit 19:16
+ 0xcf,
+ 0, /// base 31:24
+ /// 0, /// base 63:32
+ /// 0 /// reserved
+ ///
+ },
+ { /// 64-bit code Selector: selector[38]
+ 0xffff, /// limit 15:0
+ 0, /// base 15:0
+ 0, /// base 23:16
+ 0x9b, /// type & limit 19:16
+ 0xaf,
+ 0, /// base 31:24
+ /// 0, /// base 63:32
+ /// 0 /// reserved
+ ///
+ },
+ { /// Spare3 Selector: selector[40]
+ 0, /// limit 15:0
+ 0, /// base 15:0
+ 0, /// base 23:16
+ 0, /// type & limit 19:16
+ 0, /// base 31:24
+ 0,
+ ///
+ /// 0, /// base 63:32
+ /// 0 /// reserved
+ ///
+ }
+};
+
+ALIGN_16BYTE_BOUNDRY PSEUDO_DESCRIPTOR_x64 gGdtPseudoDescriptor = {
+ sizeof (gGdt) - 1,
+ (UINTN) gGdt
+};
+
+INTERRUPT_GATE_DESCRIPTOR gIdtTable[INTERRUPT_VECTOR_NUMBER] = { 0 };
+
+ALIGN_16BYTE_BOUNDRY PSEUDO_DESCRIPTOR_x64 gLidtPseudoDescriptor = {
+ sizeof (gIdtTable) - 1,
+ (UINTN) gIdtTable
+};
+
+/**
+ Init Global Descriptor table
+**/
+VOID
+InitializeSelectors (
+ VOID
+ )
+{
+ CpuLoadGlobalDescriptorTable (&gGdtPseudoDescriptor);
+}
+
+/**
+ Generic IDT Vector Handlers for the Host
+**/
+VOID
+AsmIdtVector00 (
+ VOID
+ );
+
+/**
+ Initialize Interrupt descriptor Tables
+**/
+VOID
+InitializeInterruptTables (
+ VOID
+ )
+{
+ UINT16 CodeSegment;
+ INTERRUPT_GATE_DESCRIPTOR *IdtEntry;
+ UINT8 *CurrentHandler;
+ UINT32 Index;
+
+//(AMI_CHG+)>
+#if defined(AMI_PEI_DEBUG_SUPPORT) && AMI_PEI_DEBUG_SUPPORT
+ EFI_STATUS Status;
+#endif
+//<(AMI_CHG+)
+
+ CodeSegment = CpuCodeSegment ();
+
+ IdtEntry = gIdtTable;
+ CurrentHandler = (UINT8 *) (UINTN) AsmIdtVector00;
+ for (Index = 0; Index < INTERRUPT_VECTOR_NUMBER; Index++) {
+ IdtEntry[Index].Offset15To0 = (UINT16) (UINTN) CurrentHandler;
+ IdtEntry[Index].SegmentSelector = CodeSegment;
+ IdtEntry[Index].Attributes = INTERRUPT_GATE_ATTRIBUTE;
+ ///
+ /// 8e00;
+ ///
+ IdtEntry[Index].Offset31To16 = (UINT16) ((UINTN) CurrentHandler >> 16);
+ IdtEntry[Index].Offset63To32 = (UINT32) ((UINTN) CurrentHandler >> 32);
+
+//(AMI_CHG+)>
+#if defined(AMI_PEI_DEBUG_SUPPORT) && AMI_PEI_DEBUG_SUPPORT
+ Status = mAmiDebuggerCpuProtocol->DebuggerFixUpPEIExceptionHandlers(
+ (DEBUGGER_INTERRUPT_GATE_DESCRIPTOR *)IdtEntry,
+ Index);
+#endif
+//<(AMI_CHG+)
+
+ CurrentHandler += 0x8;
+ ///
+ }
+
+ CpuLoadInterruptDescriptorTable (&gLidtPseudoDescriptor);
+
+ return;
+}
+
+/**
+ Initialize cache attributes based on MTRR
+**/
+VOID
+InitailizeCacheAttributes (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS Page;
+ EFI_CPUID_REGISTER FeatureInfo;
+ EFI_CPUID_REGISTER FunctionInfo;
+ UINT8 PhysicalAddressBits;
+ UINT32 MsrNum;
+ UINT64 TempQword;
+ UINT64 ComplementBits;
+ UINT32 VariableMtrrLimit;
+
+ VariableMtrrLimit = (UINT32) (AsmReadMsr64 (IA32_MTRR_CAP) & B_IA32_MTRR_VARIABLE_SUPPORT);
+
+ ///
+ /// Allocate 16 pages
+ ///
+ Status = (gBS->AllocatePages)(AllocateAnyPages, EfiBootServicesData, mPageStoreSize, &Page);
+ ASSERT_EFI_ERROR (Status);
+
+ mPageStore = (UINT8 *) (UINTN) Page;
+
+ ZeroMem (mPageStore, 0x1000 * mPageStoreSize);
+
+ ///
+ /// Check returned value of Eax for extended CPUID functions
+ ///
+ AsmCpuid (
+ CPUID_EXTENDED_FUNCTION,
+ &FunctionInfo.RegEax,
+ &FunctionInfo.RegEbx,
+ &FunctionInfo.RegEcx,
+ &FunctionInfo.RegEdx
+ );
+
+ PhysicalAddressBits = 36;
+
+ ///
+ /// If CPU supports extended functions, get the Physical Address size by reading EAX[7:0]
+ ///
+ if (FunctionInfo.RegEax > CPUID_EXTENDED_FUNCTION) {
+ AsmCpuid (
+ CPUID_VIR_PHY_ADDRESS_SIZE,
+ &FeatureInfo.RegEax,
+ &FeatureInfo.RegEbx,
+ &FeatureInfo.RegEcx,
+ &FeatureInfo.RegEdx
+ );
+ PhysicalAddressBits = (UINT8) FeatureInfo.RegEax;
+ }
+
+ mValidMtrrBitsMask = (((UINT64) 1) << PhysicalAddressBits) - 1;
+ mValidMtrrAddressMask = mValidMtrrBitsMask & 0xfffffffffffff000;
+
+ ComplementBits = mValidMtrrBitsMask & 0xfffffff000000000;
+ if (ComplementBits != 0) {
+ ///
+ /// Disable cache and clear the corresponding MTRR bits
+ ///
+ PreMtrrChange ();
+ for (MsrNum = CACHE_VARIABLE_MTRR_BASE;
+ MsrNum < (CACHE_VARIABLE_MTRR_BASE + VariableMtrrLimit * 2 - 1);
+ MsrNum += 2
+ ) {
+ TempQword = AsmReadMsr64 (MsrNum + 1);
+ if ((TempQword & B_CACHE_MTRR_VALID) != 0) {
+ ///
+ /// MTRR Physical Mask
+ ///
+ TempQword = TempQword | ComplementBits;
+ AsmWriteMsr64 (MsrNum + 1, TempQword);
+ }
+ }
+
+ ///
+ /// Enable Cache and set the corresponding MTRR bits
+ ///
+ PostMtrrChange ();
+ }
+}
+
+/**
+ Allocate zeroed pages
+
+ @retval Pointer to the page buffer
+**/
+VOID *
+AllocateZeroedPage (
+ VOID
+ )
+{
+ if (mPageStoreIndex >= mPageStoreSize) {
+ ///
+ /// We are out of space
+ ///
+ return NULL;
+ }
+
+ return (VOID *) (UINTN) &mPageStore[0x1000 * mPageStoreIndex++];
+}
+
+/**
+ Convert 2MB page tables to 4KB page tables
+
+ @param[in] PageAddress - Page address to convert
+ @param[in] PageDirectoryToConvert - Page table that will be converted
+**/
+VOID
+Convert2MBPageTo4KPages (
+ IN EFI_PHYSICAL_ADDRESS PageAddress,
+ IN OUT x64_PAGE_TABLE_ENTRY **PageDirectoryToConvert
+ )
+{
+ UINTN Index;
+ EFI_PHYSICAL_ADDRESS WorkingAddress;
+ x64_PAGE_TABLE_ENTRY_4K *PageTableEntry;
+ x64_PAGE_TABLE_ENTRY Attributes;
+
+ ///
+ /// Save the attributes of the 2MB table
+ ///
+ Attributes.Page2Mb.Uint64 = (*PageDirectoryToConvert)->Page2Mb.Uint64;
+
+ ///
+ /// Convert PageDirectoryEntry2MB into a 4K Page Directory
+ ///
+ PageTableEntry = AllocateZeroedPage ();
+ if (PageTableEntry == NULL) {
+ return;
+ }
+ (*PageDirectoryToConvert)->Page2Mb.Uint64 = (UINT64) PageTableEntry;
+ (*PageDirectoryToConvert)->Page2Mb.Bits.ReadWrite = 1;
+ (*PageDirectoryToConvert)->Page2Mb.Bits.Present = 1;
+
+ WorkingAddress = PageAddress;
+ for (Index = 0; Index < 512; Index++, PageTableEntry++, WorkingAddress += 0x1000) {
+ PageTableEntry->Uint64 = (UINT64) WorkingAddress;
+ PageTableEntry->Bits.Present = 1;
+
+ ///
+ /// Update the new page to have the same attributes as the 2MB page
+ ///
+ PageTableEntry->Bits.ReadWrite = Attributes.Common.ReadWrite;
+ PageTableEntry->Bits.CacheDisabled = Attributes.Common.CacheDisabled;
+ PageTableEntry->Bits.WriteThrough = Attributes.Common.WriteThrough;
+
+ if (WorkingAddress == PageAddress) {
+ ///
+ /// Return back the 4K page that matches the Working addresss
+ ///
+ *PageDirectoryToConvert = (x64_PAGE_TABLE_ENTRY *) PageTableEntry;
+ }
+ }
+}
+
+/**
+ Get current memory mapping information
+
+ @param[in] BaseAddress - get current memory mapping by this Base address
+ @param[in] PageTable - page table that translated this base address
+ @param[in] Page2MBytes - TRUE if this is 2MBytes page table
+
+ @retval EFI_NOT_FOUND - page table not found
+ @retval EFI_SUCCESS - page table found
+**/
+EFI_STATUS
+GetCurrentMapping (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ OUT x64_PAGE_TABLE_ENTRY **PageTable,
+ OUT BOOLEAN *Page2MBytes
+ )
+{
+ UINT64 Cr3;
+ x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageMapLevel4Entry;
+ x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageDirectoryPointerEntry;
+ x64_PAGE_TABLE_ENTRY_2M *PageTableEntry2Mb;
+ x64_PAGE_DIRECTORY_ENTRY_4K *PageDirectoryEntry4k;
+ x64_PAGE_TABLE_ENTRY_4K *PageTableEntry4k;
+ UINTN Pml4Index;
+ UINTN PdpIndex;
+ UINTN Pde2MbIndex;
+ UINTN PteIndex;
+
+ Cr3 = AsmReadCr3 ();
+
+ PageMapLevel4Entry = (x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *) (Cr3 & 0x000ffffffffff000);
+
+ Pml4Index = (UINTN) RShiftU64 (BaseAddress, 39) & 0x1ff;
+ if (PageMapLevel4Entry[Pml4Index].Bits.Present == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ PageDirectoryPointerEntry = (x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *) (PageMapLevel4Entry[Pml4Index].Uint64 & 0x000ffffffffff000);
+ PdpIndex = (UINTN) RShiftU64 (BaseAddress, 30) & 0x1ff;
+ if (PageDirectoryPointerEntry[PdpIndex].Bits.Present == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ PageTableEntry2Mb = (x64_PAGE_TABLE_ENTRY_2M *) (PageDirectoryPointerEntry[PdpIndex].Uint64 & 0x000ffffffffff000);
+ Pde2MbIndex = (UINTN) RShiftU64 (BaseAddress, 21) & 0x1ff;
+ if (PageTableEntry2Mb[Pde2MbIndex].Bits.Present == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (PageTableEntry2Mb[Pde2MbIndex].Bits.MustBe1 == 1) {
+ ///
+ /// We found a 2MByte page so lets return it
+ ///
+ *Page2MBytes = TRUE;
+ *PageTable = (x64_PAGE_TABLE_ENTRY *) &PageTableEntry2Mb[Pde2MbIndex].Uint64;
+ return EFI_SUCCESS;
+ }
+
+ ///
+ /// 4K page so keep walking
+ ///
+ PageDirectoryEntry4k = (x64_PAGE_DIRECTORY_ENTRY_4K *) &PageTableEntry2Mb[Pde2MbIndex].Uint64;
+
+ PageTableEntry4k = (x64_PAGE_TABLE_ENTRY_4K *) (PageDirectoryEntry4k[Pde2MbIndex].Uint64 & 0x000ffffffffff000);
+ PteIndex = (UINTN) RShiftU64 (BaseAddress, 12) & 0x1ff;
+ if (PageTableEntry4k[PteIndex].Bits.Present == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ *Page2MBytes = FALSE;
+ *PageTable = (x64_PAGE_TABLE_ENTRY *) &PageTableEntry4k[PteIndex];
+ return EFI_SUCCESS;
+}
+
+/**
+ Prepare memory for essential system tables.
+
+ @retval EFI_SUCCESS - Memory successfully prepared.
+**/
+EFI_STATUS
+PrepareMemory (
+ VOID
+ )
+{
+ ///
+ /// Allocate space to convert 2MB page tables to 4K tables.
+ /// This can not be done at call time as the TPL level will
+ /// not be correct.
+ ///
+ InitailizeCacheAttributes ();
+
+ InitializeExternalVectorTablePtr (mExternalVectorTable);
+ ///
+ /// Initialize the Interrupt Descriptor Table
+ ///
+ InitializeInterruptTables ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Prepare Wakeup Buffer and stack for APs.
+
+ @param[in] WakeUpBuffer - Pointer to the address of wakeup buffer for output.
+ @param[in] StackAddressStart - Pointer to the stack address of APs for output.
+ @param[in] MaximumCPUsForThisSystem - Maximum CPUs in this system.
+
+ @retval EFI_SUCCESS - Memory successfully prepared for APs.
+ @retval Other - Error occurred while allocating memory.
+**/
+EFI_STATUS
+PrepareMemoryForAPs (
+ OUT EFI_PHYSICAL_ADDRESS *WakeUpBuffer,
+ OUT VOID **StackAddressStart,
+ IN UINTN MaximumCPUsForThisSystem
+ )
+{
+ EFI_STATUS Status;
+ MP_ASSEMBLY_ADDRESS_MAP AddressMap;
+
+ ///
+ /// Release All APs with a lock and wait for them to retire to rendezvous procedure.
+ /// We need a page (4KB) of memory for IA-32 to use broadcast APIs, on a temporary basis.
+ ///
+ Status = AllocateWakeUpBuffer (WakeUpBuffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ///
+ /// Claim memory for AP stack
+ ///
+ Status = AllocateReservedMemoryBelow4G (
+ MaximumCPUsForThisSystem * STACK_SIZE_PER_PROC,
+ StackAddressStart
+ );
+
+ if (EFI_ERROR (Status)) {
+ (gBS->FreePages)(*WakeUpBuffer, 1);
+ return Status;
+ }
+
+ AsmGetAddressMap (&AddressMap);
+ CopyMem ((VOID *) (UINTN) *WakeUpBuffer, AddressMap.RendezvousFunnelAddress, AddressMap.Size);
+ *(UINT32 *) (UINTN) (*WakeUpBuffer + AddressMap.FlatJumpOffset + 3) = (UINT32) (*WakeUpBuffer + AddressMap.PModeEntryOffset);
+ *(UINT32 *) (UINTN) (*WakeUpBuffer + AddressMap.LongJumpOffset + 2) = (UINT32) (*WakeUpBuffer + AddressMap.LModeEntryOffset);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Prepare exchange information for APs.
+
+ @param[in] ExchangeInfo - Pointer to the exchange info buffer for output.
+ @param[in] StackAddressStart - Start address of APs' stacks.
+ @param[in] ApFunction - Address of function assigned to AP.
+ @param[in] WakeUpBuffer - Pointer to the address of wakeup buffer.
+
+ @retval EFI_SUCCESS - Exchange Info successfully prepared for APs.
+**/
+EFI_STATUS
+PrepareExchangeInfo (
+ OUT MP_CPU_EXCHANGE_INFO *ExchangeInfo,
+ IN VOID *StackAddressStart,
+ IN VOID *ApFunction,
+ IN EFI_PHYSICAL_ADDRESS WakeUpBuffer
+ )
+{
+ ZeroMem ((VOID *) ExchangeInfo, EFI_PAGE_SIZE - MP_CPU_EXCHANGE_INFO_OFFSET);
+
+ ExchangeInfo->Lock = VacantFlag;
+ ExchangeInfo->StackStart = StackAddressStart;
+ ExchangeInfo->StackSize = STACK_SIZE_PER_PROC;
+ ExchangeInfo->ApFunction = ApFunction;
+
+ CopyMem (
+ (VOID *) (UINTN) &ExchangeInfo->GdtrProfile,
+ (VOID *) (UINTN) mAcpiCpuData->GdtrProfile,
+ sizeof (PSEUDO_DESCRIPTOR)
+ );
+ CopyMem (
+ (VOID *) (UINTN) &ExchangeInfo->IdtrProfile,
+ (VOID *) (UINTN) mAcpiCpuData->IdtrProfile,
+ sizeof (PSEUDO_DESCRIPTOR)
+ );
+
+ ExchangeInfo->BufferStart = (UINT32) WakeUpBuffer;
+ ExchangeInfo->Cr3 = (UINT32) (AsmReadCr3 ());
+ ExchangeInfo->InitFlag = 1;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Prepare Wakeup Buffer and stack for APs.
+
+ @param[in] WakeUpBuffer - Pointer to the address of wakeup buffer for output.
+ @param[in] StackAddressStart - Pointer to the stack address of APs for output.
+
+ @retval EFI_SUCCESS - Memory successfully prepared for APs.
+**/
+EFI_STATUS
+S3PrepareMemoryForAPs (
+ OUT EFI_PHYSICAL_ADDRESS *WakeUpBuffer,
+ OUT VOID **StackAddressStart
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Prepare exchange information for APs.
+
+ @param[in] ExchangeInfo - Pointer to the exchange info for output.
+ @param[in] StackAddressStart - Start address of APs' stacks.
+ @param[in] ApFunction - Address of function assigned to AP.
+ @param[in] WakeUpBuffer - Pointer to the address of wakeup buffer.
+
+ @retval EFI_SUCCESS - Exchange Info successfully prepared for APs.
+**/
+EFI_STATUS
+S3PrepareExchangeInfo (
+ OUT MP_CPU_EXCHANGE_INFO *ExchangeInfo,
+ IN VOID *StackAddressStart,
+ IN VOID *ApFunction,
+ IN EFI_PHYSICAL_ADDRESS WakeUpBuffer
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Dynamically write the far jump destination in APs' wakeup buffer,
+ in order to refresh APs' CS registers for mode switching.
+**/
+VOID
+RedirectFarJump (
+ VOID
+ )
+{
+ MP_ASSEMBLY_ADDRESS_MAP AddressMap;
+
+ AsmGetAddressMap (&AddressMap);
+ *(UINT32 *) (UINTN) (mAcpiCpuData->WakeUpBuffer + AddressMap.FlatJumpOffset + 3) = (UINT32) (mAcpiCpuData->WakeUpBuffer + AddressMap.PModeEntryOffset);
+ *(UINT32 *) (UINTN) (mAcpiCpuData->WakeUpBuffer + AddressMap.LongJumpOffset + 2) = (UINT32) (mAcpiCpuData->WakeUpBuffer + AddressMap.LModeEntryOffset);
+
+ return;
+}
+
+/**
+ Prepare GDTR and IDTR for AP
+
+ @param[in] Gdtr - The GDTR profile
+ @param[in] Idtr - The IDTR profile
+
+ @retval EFI_STATUS - status returned by each sub-routine
+ @retval EFI_SUCCESS - GDTR and IDTR has been prepared for AP
+**/
+EFI_STATUS
+PrepareGdtIdtForAP (
+ OUT PSEUDO_DESCRIPTOR *Gdtr,
+ OUT PSEUDO_DESCRIPTOR *Idtr
+ )
+{
+ INTERRUPT_GATE_DESCRIPTOR *IdtForAP;
+ SEGMENT_DESCRIPTOR *GdtForAP;
+
+ PSEUDO_DESCRIPTOR *IdtrForBSP;
+ PSEUDO_DESCRIPTOR *GdtrForBSP;
+
+ UINT16 *MceHandler;
+ EFI_STATUS Status;
+
+ AsmGetGdtrIdtr (&GdtrForBSP, &IdtrForBSP);
+
+ ///
+ /// Allocate reserved memory for IDT
+ ///
+ Status = AllocateAlignedReservedMemory (
+ IdtrForBSP->Limit + 1,
+ 8,
+ (VOID **) &IdtForAP
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ///
+ /// Allocate reserved memory for GDT
+ ///
+ Status = AllocateAlignedReservedMemory (
+ GdtrForBSP->Limit + 1,
+ 8,
+ (VOID **) &GdtForAP
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = (gBS->AllocatePool)(EfiReservedMemoryType, SIZE_OF_MCE_HANDLER, (VOID **) &MceHandler);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ///
+ /// McheHandler content: iret (opcode = 0xcf)
+ ///
+ *MceHandler = 0xCF48;
+
+ CopyMem (GdtForAP, (VOID *) GdtrForBSP->Base, GdtrForBSP->Limit + 1);
+ CopyMem (IdtForAP, (VOID *) IdtrForBSP->Base, IdtrForBSP->Limit + 1);
+
+ IdtForAP[INTERRUPT_HANDLER_MACHINE_CHECK].Offset15To0 = (UINT16) (UINTN) MceHandler;
+ IdtForAP[INTERRUPT_HANDLER_MACHINE_CHECK].Offset31To16 = (UINT16) ((UINTN) MceHandler >> 16);
+ IdtForAP[INTERRUPT_HANDLER_MACHINE_CHECK].Offset63To32 = (UINT32) ((UINTN) MceHandler >> 32);
+
+ ///
+ /// Create Gdtr, IDTR profile
+ ///
+ Gdtr->Base = (UINTN) GdtForAP;
+ Gdtr->Limit = GdtrForBSP->Limit;
+
+ Idtr->Base = (UINTN) IdtForAP;
+ Idtr->Limit = IdtrForBSP->Limit;
+
+ return EFI_SUCCESS;
+}
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/x64/MpCpu.c b/ReferenceCode/Haswell/CpuInit/Dxe/x64/MpCpu.c
new file mode 100644
index 0000000..806dcc0
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/x64/MpCpu.c
@@ -0,0 +1,89 @@
+/** @file
+ MP Support functions
+
+@copyright
+ Copyright (c) 2007 - 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 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
+**/
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "MpService.h"
+#include EFI_PROTOCOL_DEFINITION (MpService)
+#endif
+
+extern EFI_CPU_MICROCODE_HEADER **mMicrocodePointerBuffer;
+
+ACPI_CPU_DATA *mAcpiCpuData;
+MP_SYSTEM_DATA *mMPSystemData;
+
+///
+/// Function declarations
+///
+/**
+ Initializes MP support in the system.
+
+ @retval EFI_SUCCESS - Multiple processors are initialized successfully.
+ @retval EFI_OUT_OF_RESOURCES - No enough resoruces (such as out of memory).
+**/
+EFI_STATUS
+InitializeMpSupport (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ MP_CPU_RESERVED_DATA *MpCpuReservedData;
+
+ ///
+ /// Allocate memory for MP CPU related data below 4G
+ ///
+ Status = AllocateReservedMemoryBelow4G (
+ sizeof (MP_CPU_RESERVED_DATA),
+ (VOID **) &MpCpuReservedData
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ZeroMem (MpCpuReservedData, sizeof (MP_CPU_RESERVED_DATA));
+
+ mMPSystemData = &(MpCpuReservedData->MPSystemData);
+ mAcpiCpuData = &(MpCpuReservedData->AcpiCpuData);
+
+ ///
+ /// Copy microcode to allocated memory
+ ///
+ CopyMem (
+ MpCpuReservedData->MicrocodePointerBuffer,
+ mMicrocodePointerBuffer,
+ sizeof (EFI_CPU_MICROCODE_HEADER *) * (NUMBER_OF_MICROCODE_UPDATE + 1)
+ );
+
+ ///
+ /// Initialize ACPI_CPU_DATA data
+ ///
+ mAcpiCpuData->CpuPrivateData = (EFI_PHYSICAL_ADDRESS) (UINTN) (&(mMPSystemData->S3DataPointer));
+ mAcpiCpuData->S3BootPath = FALSE;
+ mAcpiCpuData->MicrocodePointerBuffer = (EFI_PHYSICAL_ADDRESS) MpCpuReservedData->MicrocodePointerBuffer;
+ mAcpiCpuData->GdtrProfile = (EFI_PHYSICAL_ADDRESS) & (MpCpuReservedData->GdtrProfile);
+ mAcpiCpuData->IdtrProfile = (EFI_PHYSICAL_ADDRESS) & (MpCpuReservedData->IdtrProfile);
+
+ ///
+ /// Initialize MP services
+ ///
+ InitializeMpServices ();
+
+ return EFI_SUCCESS;
+}
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/x64/MpEqu.inc b/ReferenceCode/Haswell/CpuInit/Dxe/x64/MpEqu.inc
new file mode 100644
index 0000000..f7c97ad
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/x64/MpEqu.inc
@@ -0,0 +1,51 @@
+;@file
+; @todo ADD DESCRIPTION
+;
+;@copyright
+; Copyright (c) 2005 - 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
+;
+
+VacantFlag Equ 00h
+NotVacantFlag Equ 0ffh
+BreakToRunApSignal Equ 6E755200h
+MonitorFilterSize Equ 40h
+WakeUpApCounterInit Equ 0
+WakeUpApPerHltLoop Equ 1
+WakeUpApPerMwaitLoop Equ 2
+WakeUpApPerRunLoop Equ 3
+WakeUpApPerMwaitLoop32 Equ 4
+WakeUpApPerRunLoop32 Equ 5
+
+LockLocation equ 1000h - 0400h
+StackStartAddressLocation equ LockLocation + 08h
+StackSizeLocation equ LockLocation + 10h
+CProcedureLocation equ LockLocation + 18h
+GdtrLocation equ LockLocation + 20h
+IdtrLocation equ LockLocation + 2Ah
+BufferStartLocation equ LockLocation + 34h
+Cr3OffsetLocation equ LockLocation + 38h
+InitFlagLocation equ LockLocation + 3Ch
+WakeUpApManner equ LockLocation + 40h
+BistBuffer equ LockLocation + 44h
+
+PAUSE32 MACRO
+ DB 0F3h
+ DB 090h
+ ENDM
+
+;-------------------------------------------------------------------------------
+
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/x64/MpFuncs.asm b/ReferenceCode/Haswell/CpuInit/Dxe/x64/MpFuncs.asm
new file mode 100644
index 0000000..58714f8
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/x64/MpFuncs.asm
@@ -0,0 +1,618 @@
+;
+; 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 - 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.
+;
+;
+; Module Name:
+;
+; MpFuncs.asm
+;
+; Abstract:
+;
+; This is the assembly code for EM64T MP support
+;
+;-------------------------------------------------------------------------------
+
+
+include MpEqu.inc
+CpuInitFloatPointUnit PROTO C
+
+;-------------------------------------------------------------------------------------
+
+;-------------------------------------------------------------------------------------
+;RendezvousFunnelProc procedure follows. All APs execute their procedure. This
+;procedure serializes all the AP processors through an Init sequence. It must be
+;noted that APs arrive here very raw...ie: real mode, no stack.
+;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
+;IS IN MACHINE CODE.
+;-------------------------------------------------------------------------------------
+;RendezvousFunnelProc (&WakeUpBuffer,MemAddress);
+
+text SEGMENT
+
+RendezvousFunnelProc PROC PUBLIC
+RendezvousFunnelProcStart::
+
+; At this point CS = 0x(vv00) and ip= 0x0.
+ db 66h, 08bh, 0e8h ; mov ebp, eax
+
+ db 8ch, 0c8h ; mov ax, cs
+ db 8eh, 0d8h ; mov ds, ax
+ db 8eh, 0c0h ; mov es, ax
+ db 8eh, 0d0h ; mov ss, ax
+ db 33h, 0c0h ; xor ax, ax
+ db 8eh, 0e0h ; mov fs, ax
+ db 8eh, 0e8h ; mov gs, ax
+
+; Get APIC ID
+;
+ db 66h, 0B8h
+ dd 00000001h ; mov eax, 1
+ db 0Fh, 0A2h ; cpuid
+ db 66h, 0C1h, 0EBh, 18h ; shr ebx, 24
+ db 66h, 81h, 0E3h
+ dd 000000FFh ; and ebx, 0ffh ; EBX is APIC ID
+
+; If it is the first time AP wakes up, just record AP's BIST
+; Otherwise, switch to protected mode.
+
+ db 0BEh ; opcode of mov si, imm16
+ dw InitFlagLocation ; mov si, InitFlag
+ db 66h, 83h, 3Ch, 00h ; cmp dword ptr [si], 0
+ db 74h ; opcode of jz
+ db flat32Start - ($ + 1) ; jz flat32Start
+
+; Record BIST information
+;
+ db 0B0h, 08h ; mov al, 8
+ db 0F6h, 0E3h ; mul bl
+
+ db 0BEh ; opcode of mov si, imm16
+ dw BistBuffer ; mov si, BistBuffer
+ db 03h, 0F0h ; add si, ax
+
+ db 66h, 0C7h, 04h
+ dd 00000001h ; mov dword ptr [si], 1 ; Set Valid Flag
+ db 66h, 89h, 6Ch, 04h ; mov dword ptr [si + 4], ebp ; Store BIST value
+
+;
+; Switch to flat mode.
+;
+flat32Start::
+
+ db 0BFh ; opcode of mov di, imm16
+ dw BufferStartLocation ; mov di, BufferStartLocation
+ db 66h, 8Bh, 35h ; mov esi,dword ptr [di] ; ESI is keeping the start address of wakeup buffer
+
+ db 0BFh ; opcode of mov di, imm16
+ dw Cr3OffsetLocation ; mov di, Cr3Location
+ db 66h, 8Bh, 0Dh ; mov ecx,dword ptr [di] ; ECX is keeping the value of CR3
+
+ db 0BFh ; opcode of mov di, imm16
+ dw GdtrLocation ; mov di, GdtrProfile
+ db 66h ; db 66h
+ db 2Eh, 0Fh, 01h, 15h ; lgdt fword ptr cs:[di]
+
+ db 0BFh ; opcode of mov di, imm16
+ dw IdtrLocation ; mov di, IdtrProfile
+ db 66h ; db 66h
+ db 2Eh, 0Fh, 01h, 1Dh ; lidt fword ptr cs:[di]
+
+ db 0BFh ; opcode of mov di, imm16
+ dw LongModeStartJump - RendezvousFunnelProcStart ; Get offset of LongModeStartJump
+ db 66h, 8Bh, 3Dh ; mov edi,dword ptr [di] ; EDI is keeping the LongModeStart Jump Address
+
+ db 31h, 0C0h ; xor ax, ax
+ db 8Eh, 0D8h ; mov ds, ax
+
+ db 0Fh, 20h, 0C0h ; mov eax, cr0 ; Get control register 0
+ db 66h, 83h, 0C8h, 03h ; or eax, 000000003h ; Set PE bit (bit #0) and MP
+ db 0Fh, 22h, 0C0h ; mov cr0, eax
+
+FLAT32_JUMP::
+
+ db 66h, 67h, 0EAh ; far jump
+ dd 0h ; 32-bit offset
+ dw 20h ; 16-bit selector
+
+NemInit:: ; 32-bits protected mode entry point
+
+ db 66h, 0B8h, 18h, 00h ; mov ax, 18h
+ db 66h, 8Eh, 0D8h ; mov ds, ax
+ db 66h, 8Eh, 0C0h ; mov es, ax
+ db 66h, 8Eh, 0E0h ; mov fs, ax
+ db 66h, 8Eh, 0E8h ; mov gs, ax
+ db 66h, 8Eh, 0D0h ; mov ss, ax ; Flat mode setup.
+
+
+PrepareToGoLongMode64::
+
+ db 0Fh, 20h, 0E0h ; mov eax, cr4
+ db 66h, 0Dh, 020h, 06h ; or ax, 0620h ; Set PAE=1, OSFXSR=1, OSXMMEXCPT=1.
+ db 0Fh, 22h, 0E0h ; mov cr4, eax
+
+ db 0Fh, 22h, 0D9h ; mov cr3, ecx
+
+ db 0B9h
+ dd 0C0000080h ; mov ecx, 0c0000080h ; EFER MSR number.
+ db 0Fh, 32h ; rdmsr ; Read EFER.
+ db 0Fh, 0BAh, 0E8h, 08h ; bts eax, 8 ; Set LME=1.
+ db 0Fh, 30h ; wrmsr ; Write EFER.
+
+ db 0Fh, 20h, 0C0h ; mov eax, cr0 ; Read CR0.
+ db 0Fh, 0BAh, 0E8h, 1Fh ; bts eax, 31 ; Set PG=1.
+ db 0Fh, 22h, 0C0h ; mov cr0, eax ; Write CR0.
+
+LONG_JUMP::
+
+ db 67h, 0EAh ; far jump
+
+LongModeStartJump:
+
+ dd 0h ; 32-bit offset
+ dw 38h ; 16-bit selector
+
+
+LongModeStart::
+
+ mov ax, 30h
+ mov ds, ax
+ mov es, ax
+ mov ss, ax
+
+WaitFirstApTaskAssigned::
+;
+; First INIT-SIPI-SIPI will loop here until DetailedMpInitialization function assigned for each AP
+;
+ pause
+ cmp qword ptr [esi+CProcedureLocation], 0
+ jz WaitFirstApTaskAssigned
+
+;
+; Patch Addresses for jumping between RUN and MONITOR MWAIT loops 32-bits and Long Monde Procedure 64-bits
+; Based on the running address of LongModeStart in physic memory which was actually copied by CPU DXE INIT
+;
+ xor rdx, rdx
+ mov eax, edi
+ add eax, RunLoopAndMwaitLoop32 - LongModeStart
+ mov edx, edi
+ add edx, RunLoopAndMwaitLoop32Jump - LongModeStart
+ mov dword ptr [rdx], eax
+
+ mov rbp, rdx ; RBP = 32-bits compatibility mode FAR JUMP m16:32 operand pointer
+
+ mov eax, edi
+ add eax, RunLoopAndMwaitLoop64 - LongModeStart
+ mov edx, edi
+ add edx, RunLoopAndMwaitLoop64Jump - LongModeStart
+ mov dword ptr [rdx], eax
+
+;
+; ProgramStack
+;
+ xor rcx, rcx
+ mov edi, esi
+ add edi, BistBuffer
+ mov ecx, dword ptr [edi + 8 * ebx] ; RCX = CpuNumber
+
+ mov edi, esi
+ add edi, StackSizeLocation
+ mov rax, qword ptr [edi]
+ inc rcx
+ mul rcx ; RAX = StackSize * (CpuNumber + 1)
+
+ mov edi, esi
+ add edi, StackStartAddressLocation
+ mov rdx, qword ptr [edi]
+ add rax, rdx ; RAX = StackStart + StackSize * (CpuNumber + 1)
+
+ mov rsp, rax
+ sub rsp, MonitorFilterSize ; Reserved Monitor data space
+ or ebx, BreakToRunApSignal ; ebx = #Cpu run signature
+
+;
+; Call assembly function to initialize FPU.
+;
+ mov rax, CpuInitFloatPointUnit
+ sub rsp, 20h
+ call rax
+ add rsp, 20h
+
+;
+; Load C Function pointer and wakeup manner location
+;
+ mov edi, esi
+ add edi, CProcedureLocation
+ add esi, WakeUpApManner ; esi = WakeUpApManner Address Location
+
+WakeUpThisAp64::
+
+ mov rax, qword ptr [edi]
+
+ test rax, rax
+ jz CheckWakeUpCounterInit64
+
+ push rbp
+ push rbx
+ push rsi
+ push rdi
+
+ sub rsp, 20h
+ call rax
+ add rsp, 20h
+
+ pop rdi
+ pop rsi
+ pop rbx
+ pop rbp
+
+CheckWakeUpCounterInit64::
+
+ cmp dword ptr [esi], WakeUpApCounterInit
+ jnz CheckWakeUpManner64
+
+;
+; Initialize MONITOR_MWAIT_DATA data structure per thread
+;
+ xor rcx, rcx
+ mov qword ptr [rsp + 0], rcx ; BreakToRunApSignal
+ mov qword ptr [rsp + 8], rcx ; HltLoopBreakCounter
+ mov qword ptr [rsp + 16], rcx ; MwaitLoopBreakCounter
+ mov qword ptr [rsp + 24], rcx ; RunLoopBreakCounter
+ mov qword ptr [rsp + 32], rcx ; MwaitLoopBreakCounter32
+ mov qword ptr [rsp + 40], rcx ; RunLoopBreakCounter32
+ mov qword ptr [rsp + 48], rcx ; WakeUpApVectorChangeFlag
+ mov qword ptr [rsp + 56], rcx ; MwaitTargetCstate
+
+WaitWakeUpMannerAssigned::
+
+ pause
+ cmp dword ptr [esi], WakeUpApCounterInit
+ jz WaitWakeUpMannerAssigned
+
+CheckWakeUpManner64::
+
+ pause
+ mov edx, dword ptr [esi]
+ cmp edx, WakeUpApPerHltLoop
+ jz HltApLoop64
+
+ cmp edx, WakeUpApPerMwaitLoop
+ jz ApMwaitLoop64
+
+ cmp edx, WakeUpApPerRunLoop
+ jz CheckRunSignal64
+
+ jmp JumpToCompatibility32Mode
+
+ApMwaitLoop64::
+
+ cli
+ mov rax, rsp ; Set Monitor Address
+ xor rcx, rcx
+ xor rdx, rdx
+ DB 0fh, 1, 0c8h ; MONITOR
+ mov rax, qword ptr [rsp + 56] ; Mwait Target C-State per rax[7:4]
+ DB 0fh, 1, 0c9h ; MWAIT
+
+CheckRunSignal64::
+
+ cmp qword ptr [rsp], rbx ; Check if run signal correct?
+ jnz CheckWakeUpManner64 ; Unknown break, go checking run manner
+
+ jmp WakeUpThisAp64 ; Jmp to execute AP task
+
+HltApLoop64::
+
+ cli
+ hlt
+ jmp HltApLoop64 ; Jump to halt loop
+
+
+JumpToCompatibility32Mode::
+
+ db 0FFh, 6Dh, 0 ; jmp pword ptr [rbp+0] ; Far jump to m16:32 for 32-bits compatibility mode
+
+RunLoopAndMwaitLoop32Jump:
+
+ dd 0h ; m32 part of m16:32
+ dw 20h ; m16 part of m16:32
+
+RunLoopAndMwaitLoop32::
+
+ db 66h, 0B8h, 18h, 00h ; mov ax, 18h
+ db 66h, 8Eh, 0D8h ; mov ds, ax
+ db 8eh, 0d0h ; mov ss, ax
+
+ db 0Fh, 20h, 0C0h ; mov eax, cr0 ; Read CR0.
+ db 0Fh, 0BAh, 0F0h, 1Fh ; btr eax, 31 ; Reset PG=0.
+ db 0Fh, 22h, 0C0h ; mov cr0, eax ; Write CR0.
+
+ db 0B9h
+ dd 0C0000080h ; mov ecx, 0c0000080h ; EFER MSR number.
+ db 0Fh, 32h ; rdmsr ; Read EFER.
+ db 0Fh, 0BAh, 0F0h, 08h ; btr eax, 8 ; Reset LME=0.
+ db 0Fh, 30h ; wrmsr ; Write EFER.
+
+ db 0Fh, 20h, 0E0h ; mov eax, cr4
+ db 24h, 0DFh ; and al, 0DFh ; Reset PAE=0 in CR4 bit 5
+ db 0Fh, 22h, 0E0h ; mov cr4, eax
+
+CheckWakeUpManner32::
+
+ pause
+ cmp dword ptr [rsi], WakeUpApPerMwaitLoop32 ; Use rsi for esi per compling in 64-bits mode
+ jnz CheckRunSignal32
+
+ cli
+ mov eax, esp ; Set Monitor Address
+ xor ecx, ecx
+ xor edx, edx
+ DB 0fh, 1, 0c8h ; MONITOR
+ mov eax, dword ptr [rsp + 56] ; Mwait Target C-State per eax[7:4]
+ DB 0fh, 1, 0c9h ; MWAIT
+
+
+CheckRunSignal32::
+
+ cmp dword ptr [rsp], ebx ; Check if run signal correct?
+ jnz CheckWakeUpManner32 ; Unknown break, go checking run manner
+
+ db 0Fh, 20h, 0E0h ; mov eax, cr4
+ db 0Ch, 20h ; or al, 20h ; Set PAE=1 in CR4 bit 5
+ db 0Fh, 22h, 0E0h ; mov cr4, eax
+
+ db 0B9h
+ dd 0C0000080h ; mov ecx, 0c0000080h ; EFER MSR number.
+ db 0Fh, 32h ; rdmsr ; Read EFER.
+ db 0Fh, 0BAh, 0E8h, 08h ; bts eax, 8 ; Set LME=1.
+ db 0Fh, 30h ; wrmsr ; Write EFER.
+
+ db 0Fh, 20h, 0C0h ; mov eax, cr0 ; Read CR0.
+ db 0Fh, 0BAh, 0E8h, 1Fh ; bts eax, 31 ; Set PG=1.
+ db 0Fh, 22h, 0C0h ; mov cr0, eax ; Write CR0.
+
+ db 67h, 0EAh ; far jump back to 64-bits long mode
+
+RunLoopAndMwaitLoop64Jump:
+
+ dd 0h ; 32-bit offset
+ dw 38h ; 16-bit selector
+
+RunLoopAndMwaitLoop64::
+
+ mov ax, 30h
+ mov ds, ax
+ mov ss, ax
+
+ jmp WakeUpThisAp64
+
+RendezvousFunnelProc ENDP
+RendezvousFunnelProcEnd::
+
+
+;-------------------------------------------------------------------------------------
+; AsmGetAddressMap (&AddressMap);
+;-------------------------------------------------------------------------------------
+AsmGetAddressMap PROC PUBLIC
+
+ mov rax, offset RendezvousFunnelProcStart
+ mov qword ptr [rcx], rax
+ mov qword ptr [rcx+8h], NemInit - RendezvousFunnelProcStart
+ mov qword ptr [rcx+10h], FLAT32_JUMP - RendezvousFunnelProcStart
+ mov qword ptr [rcx+18h], LongModeStart - RendezvousFunnelProcStart
+ mov qword ptr [rcx+20h], LONG_JUMP - RendezvousFunnelProcStart
+ mov qword ptr [rcx+28h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
+
+ ret
+
+AsmGetAddressMap ENDP
+
+AsmGetGdtrIdtr PROC PUBLIC
+
+ sgdt GdtDesc
+ lea rax, GdtDesc
+ mov [rcx], rax
+
+ sidt IdtDesc
+ lea rax, IdtDesc
+ mov [rdx], rax
+
+ ret
+
+AsmGetGdtrIdtr ENDP
+
+AsmAcquireMPLock PROC PUBLIC
+
+ mov al, NotVacantFlag
+TryGetLock:
+ xchg al, byte ptr [rcx]
+ cmp al, VacantFlag
+ jz LockObtained
+
+ pause
+ jmp TryGetLock
+
+LockObtained:
+ ret
+
+AsmAcquireMPLock ENDP
+
+AsmReleaseMPLock PROC PUBLIC
+
+ mov al, VacantFlag
+ xchg al, byte ptr [rcx]
+
+ ret
+
+AsmReleaseMPLock ENDP
+
+;-------------------------------------------------------------------------------------
+;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is
+;about to become an AP. It switches it'stack with the current AP.
+;AsmExchangeRole (IN CPU_EXCHANGE_INFO *MyInfo, IN CPU_EXCHANGE_INFO *OthersInfo);
+;-------------------------------------------------------------------------------------
+CPU_SWITCH_STATE_IDLE equ 0
+CPU_SWITCH_STATE_STORED equ 1
+CPU_SWITCH_STATE_LOADED equ 2
+
+AsmExchangeRole PROC PUBLIC
+ ; DO NOT call other functions in this function, since 2 CPU may use 1 stack
+ ; at the same time. If 1 CPU try to call a functiosn, stack will be corrupted.
+
+ push rax
+ push rbx
+ push rcx
+ push rdx
+ push rsi
+ push rdi
+ push rbp
+ push r8
+ push r9
+ push r10
+ push r11
+ push r12
+ push r13
+ push r14
+ push r15
+
+ mov rax, cr0
+ push rax
+
+ mov rax, cr4
+ push rax
+
+ ; rsi contains MyInfo pointer
+ mov rsi, rcx
+
+ ; rdi contains OthersInfo pointer
+ mov rdi, rdx
+
+ ;Store EFLAGS, GDTR and IDTR regiter to stack
+ pushfq
+ sgdt fword ptr [rsi + 16]
+ sidt fword ptr [rsi + 26]
+
+ ; Store the its StackPointer
+ mov qword ptr [rsi + 8], rsp
+
+ ; update its switch state to STORED
+ mov al, NotVacantFlag
+TryLock1:
+ lock xchg al, byte ptr [rsi]
+ cmp al, VacantFlag
+ jz LockObtained1
+ pause
+ jmp TryLock1
+
+LockObtained1:
+ mov byte ptr [rsi + 1], CPU_SWITCH_STATE_STORED
+ lock xchg al, byte ptr [rsi]
+
+WaitForOtherStored::
+ ; wait until the other CPU finish storing its state
+ mov al, NotVacantFlag
+TryLock2:
+ lock xchg al, byte ptr [rdi]
+ cmp al, VacantFlag
+ jz LockObtained2
+ PAUSE32
+ jmp TryLock2
+
+LockObtained2:
+ mov bl, byte ptr [rdi + 1]
+ lock xchg al, byte ptr [rdi]
+ cmp bl, CPU_SWITCH_STATE_STORED
+ jb WaitForOtherStored
+
+ ; Since another CPU already stored its state, load them
+ ; load GDTR value
+ lgdt fword ptr [rdi + 16]
+
+ ; load IDTR value
+ lidt fword ptr [rdi + 26]
+
+ ; load its future StackPointer
+ mov rsp, qword ptr [rdi + 8]
+
+ ; update its switch state to LOADED
+ mov al, NotVacantFlag
+TryLock3:
+ lock xchg al, byte ptr [rsi]
+ cmp al, VacantFlag
+ jz LockObtained3
+ PAUSE32
+ jmp TryLock3
+
+LockObtained3:
+ mov byte ptr [rsi+1], CPU_SWITCH_STATE_LOADED
+ lock xchg al, byte ptr [rsi]
+
+WaitForOtherLoaded::
+ ; wait until the other CPU finish loading new state,
+ ; otherwise the data in stack may corrupt
+ mov al, NotVacantFlag
+TryLock4:
+ lock xchg al, byte ptr [rdi]
+ cmp al, VacantFlag
+ jz LockObtained4
+ PAUSE32
+ jmp TryLock4
+
+LockObtained4:
+ mov bl, byte ptr [rdi+1]
+ lock xchg al, byte ptr [rdi]
+ cmp bl, CPU_SWITCH_STATE_LOADED
+ jb WaitForOtherLoaded
+
+ ; since the other CPU already get the data it want, leave this procedure
+ popfq
+
+ pop rax
+ mov cr4, rax
+
+ pop rax
+ mov cr0, rax
+
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ pop r11
+ pop r10
+ pop r9
+ pop r8
+ pop rbp
+ pop rdi
+ pop rsi
+ pop rdx
+ pop rcx
+ pop rbx
+ pop rax
+
+ ret
+AsmExchangeRole ENDP
+
+GdtDesc QWORD 0
+ WORD 0
+
+IdtDesc QWORD 0
+ WORD 0
+
+text ENDS
+
+END
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/x64/ProcessorDef.h b/ReferenceCode/Haswell/CpuInit/Dxe/x64/ProcessorDef.h
new file mode 100644
index 0000000..28e55d7
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/x64/ProcessorDef.h
@@ -0,0 +1,57 @@
+/** @file
+ Definition for EM64T processor
+
+@copyright
+ Copyright (c) 2006 - 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 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
+**/
+#ifndef _PROCESSOR_DEF_H
+#define _PROCESSOR_DEF_H
+
+#pragma pack(1)
+
+typedef struct {
+ UINT16 Offset15To0;
+ UINT16 SegmentSelector;
+ UINT16 Attributes;
+ UINT16 Offset31To16;
+ UINT32 Offset63To32;
+ UINT32 Reserved;
+} INTERRUPT_GATE_DESCRIPTOR;
+
+#pragma pack()
+
+typedef struct {
+ UINT8 *RendezvousFunnelAddress;
+ UINTN PModeEntryOffset;
+ UINTN FlatJumpOffset;
+ UINTN LModeEntryOffset;
+ UINTN LongJumpOffset;
+ UINTN Size;
+} MP_ASSEMBLY_ADDRESS_MAP;
+
+VOID
+AsmGetAddressMap (
+ OUT MP_ASSEMBLY_ADDRESS_MAP *AddressMap
+ )
+/**
+@brief
+ Get address map of RendezvousFunnelProc.
+
+ @param[in] AddressMap - Output buffer for address map information
+**/
+;
+
+#endif
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/x64/VirtualMemory.h b/ReferenceCode/Haswell/CpuInit/Dxe/x64/VirtualMemory.h
new file mode 100644
index 0000000..f9bcc82
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Dxe/x64/VirtualMemory.h
@@ -0,0 +1,145 @@
+/** @file
+
+@brief:
+
+ x64 Long Mode Virtual Memory Management Definitions
+
+ References:
+ 1) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 1:Basic Architecture, Intel
+ 2) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel
+ 3) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel
+ 4) AMD64 Architecture Programmer's Manual Volume 2: System Programming
+
+@copyright
+ Copyright (c) 2004 - 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 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
+**/
+#ifndef _VIRTUAL_MEMORY_H_
+#define _VIRTUAL_MEMORY_H_
+
+#pragma pack(1)
+///
+/// Page-Map Level-4 Offset (PML4) and
+///Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB
+///
+typedef union {
+ struct {
+ UINT64 Present : 1; /// 0 = Not present in memory, 1 = Present in memory
+ UINT64 ReadWrite : 1; /// 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor : 1; /// 0 = Supervisor, 1=User
+ UINT64 WriteThrough : 1; /// 0 = Write-Back caching, 1=Write-Through caching
+ UINT64 CacheDisabled : 1; /// 0 = Cached, 1=Non-Cached
+ UINT64 Accessed : 1; /// 0 = Not accessed, 1 = Accessed (set by CPU)
+ UINT64 Reserved : 1; /// Reserved
+ UINT64 MustBeZero : 2; /// Must Be Zero
+ UINT64 Available : 3; /// Available for use by system software
+ UINT64 PageTableBaseAddress : 40; /// Page Table Base Address
+ UINT64 AvabilableHigh : 11; /// Available for use by system software
+ UINT64 Nx : 1; /// No Execute bit
+ } Bits;
+ UINT64 Uint64;
+} x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K;
+
+///
+/// Page-Directory Offset 4K
+///
+typedef union {
+ struct {
+ UINT64 Present : 1; /// 0 = Not present in memory, 1 = Present in memory
+ UINT64 ReadWrite : 1; /// 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor : 1; /// 0 = Supervisor, 1=User
+ UINT64 WriteThrough : 1; /// 0 = Write-Back caching, 1=Write-Through caching
+ UINT64 CacheDisabled : 1; /// 0 = Cached, 1=Non-Cached
+ UINT64 Accessed : 1; /// 0 = Not accessed, 1 = Accessed (set by CPU)
+ UINT64 Reserved : 1; /// Reserved
+ UINT64 MustBeZero : 1; /// Must Be Zero
+ UINT64 Reserved2 : 1; /// Reserved
+ UINT64 Available : 3; /// Available for use by system software
+ UINT64 PageTableBaseAddress : 40; /// Page Table Base Address
+ UINT64 AvabilableHigh : 11; /// Available for use by system software
+ UINT64 Nx : 1; /// No Execute bit
+ } Bits;
+ UINT64 Uint64;
+} x64_PAGE_DIRECTORY_ENTRY_4K;
+
+///
+/// Page Table Entry 4K
+///
+typedef union {
+ struct {
+ UINT64 Present : 1; /// 0 = Not present in memory, 1 = Present in memory
+ UINT64 ReadWrite : 1; /// 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor : 1; /// 0 = Supervisor, 1=User
+ UINT64 WriteThrough : 1; /// 0 = Write-Back caching, 1=Write-Through caching
+ UINT64 CacheDisabled : 1; /// 0 = Cached, 1=Non-Cached
+ UINT64 Accessed : 1; /// 0 = Not accessed, 1 = Accessed (set by CPU)
+ UINT64 Dirty : 1; /// 0 = Not Dirty, 1 = written by processor on access to page
+ UINT64 PAT : 1; /// 0 = Ignore Page Attribute Table
+ UINT64 Global : 1; /// 0 = Not global page, 1 = global page TLB not cleared on CR3 write
+ UINT64 Available : 3; /// Available for use by system software
+ UINT64 PageTableBaseAddress : 40; /// Page Table Base Address
+ UINT64 AvabilableHigh : 11; /// Available for use by system software
+ UINT64 Nx : 1; /// 0 = Execute Code, 1 = No Code Execution
+ } Bits;
+ UINT64 Uint64;
+} x64_PAGE_TABLE_ENTRY_4K;
+
+///
+/// Page Table Entry 2MB
+///
+typedef union {
+ struct {
+ UINT64 Present : 1; /// 0 = Not present in memory, 1 = Present in memory
+ UINT64 ReadWrite : 1; /// 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor : 1; /// 0 = Supervisor, 1=User
+ UINT64 WriteThrough : 1; /// 0 = Write-Back caching, 1=Write-Through caching
+ UINT64 CacheDisabled : 1; /// 0 = Cached, 1=Non-Cached
+ UINT64 Accessed : 1; /// 0 = Not accessed, 1 = Accessed (set by CPU)
+ UINT64 Dirty : 1; /// 0 = Not Dirty, 1 = written by processor on access to page
+ UINT64 MustBe1 : 1; /// Must be 1
+ UINT64 Global : 1; /// 0 = Not global page, 1 = global page TLB not cleared on CR3 write
+ UINT64 Available : 3; /// Available for use by system software
+ UINT64 PAT : 1; ///
+ UINT64 MustBeZero : 8; /// Must be zero;
+ UINT64 PageTableBaseAddress : 31; /// Page Table Base Address
+ UINT64 AvabilableHigh : 11; /// Available for use by system software
+ UINT64 Nx : 1; /// 0 = Execute Code, 1 = No Code Execution
+ } Bits;
+ UINT64 Uint64;
+} x64_PAGE_TABLE_ENTRY_2M;
+
+typedef union {
+ UINT64 Present : 1; /// 0 = Not present in memory, 1 = Present in memory
+ UINT64 ReadWrite : 1; /// 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor : 1; /// 0 = Supervisor, 1=User
+ UINT64 WriteThrough : 1; /// 0 = Write-Back caching, 1=Write-Through caching
+ UINT64 CacheDisabled : 1; /// 0 = Cached, 1=Non-Cached
+ UINT64 Accessed : 1; /// 0 = Not accessed, 1 = Accessed (set by CPU)
+ UINT64 Dirty : 1; /// 0 = Not Dirty, 1 = written by processor on access to page
+ UINT64 Reserved : 57;
+} x64_PAGE_TABLE_ENTRY_COMMON;
+
+typedef union {
+ x64_PAGE_TABLE_ENTRY_4K Page4k;
+ x64_PAGE_TABLE_ENTRY_2M Page2Mb;
+ x64_PAGE_TABLE_ENTRY_COMMON Common;
+} x64_PAGE_TABLE_ENTRY;
+
+///
+/// BugBug: x64 New stuff
+///
+#pragma pack()
+
+#endif
diff --git a/ReferenceCode/Haswell/CpuInit/Pei/BootGuardInit.c b/ReferenceCode/Haswell/CpuInit/Pei/BootGuardInit.c
new file mode 100644
index 0000000..f877784
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Pei/BootGuardInit.c
@@ -0,0 +1,111 @@
+/** @file
+ EFI 2.0 PEIM to initialize the cache and load the BSP microcode
+
+@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 an 'Intel Pre-EFI 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
+
+**/
+
+///
+/// External include files do NOT need to be explicitly specified in real EDKII
+/// environment
+///
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGluePeim.h"
+#include "CpuInitPeim.h"
+#include "CpuAccess.h"
+#include "BootGuardLibrary.h"
+#include "MeAccess.h"
+#include "HeciRegs.h"
+#endif
+
+VOID
+BootGuardInit (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_CPU_PLATFORM_POLICY_PPI *CpuPlatformPolicyPpi
+ )
+/**
+
+ Perform the platform spefific initializations.
+
+ @param[in] PeiServices - Indirect reference to the PEI Services Table.
+ @param[in] CpuPlatformPolicyPpi - Platform Policy PPI
+
+**/
+{
+ UINT32 MsrValue;
+ UINT32 MeFwSts4;
+ UINT32 BootGuardAcmStatus;
+
+ if (CpuPlatformPolicyPpi->SecurityConfig->BootGuardConfig == NULL) {
+ return;
+ }
+
+ ///
+ /// Check if System Supports Boot Guard
+ ///
+ if( IsBootGuardSupported() ) {
+ CpuPlatformPolicyPpi->SecurityConfig->BootGuardConfig->BootGuardSupport = TRUE;
+
+ BootGuardAcmStatus = *(UINT32 *) (UINTN) (TXT_PUBLIC_BASE + R_CPU_BOOT_GUARD_ACM_STATUS);
+ DEBUG ((EFI_D_INFO, "Boot Guard ACM Status = %x\n", BootGuardAcmStatus));
+
+ ///
+ /// Check Bit 12 in ME FWSTS4 to check if TPM_DISCONNECT_ALL bit is set
+ /// or ENF Shutdown path is taken by ME FW.
+ /// Also Identify any failures in ACM
+ ///
+ MeFwSts4 = HeciPciRead32(R_ME_HFS_4);
+ DEBUG ((EFI_D_INFO, "ME FW STS 4 = %x\n", MeFwSts4));
+ if((MeFwSts4 & (B_TPM_DISCONNECT | B_BOOT_GUARD_ENF_MASK)) || (BootGuardAcmStatus & B_BOOT_GUARD_ACM_ERRORCODE_MASK)) {
+ DEBUG ((EFI_D_INFO, "All TPM's on Platform are Disconnected\n"));
+ CpuPlatformPolicyPpi->SecurityConfig->BootGuardConfig->DisconnectAllTpms = TRUE;
+ }
+ CpuPlatformPolicyPpi->SecurityConfig->BootGuardConfig->BypassTpmInit = FALSE;
+ CpuPlatformPolicyPpi->SecurityConfig->BootGuardConfig->MeasuredBoot = FALSE;
+
+ if(MeFwSts4 & BIT10) {
+ DEBUG ((EFI_D_INFO, "Sx Resume Type Identified - TPM Event Log not required for ACM Measurements\n"));
+ CpuPlatformPolicyPpi->SecurityConfig->BootGuardConfig->ByPassTpmEventLog = TRUE;
+ }
+ ///
+ /// Check bit 0 of BOOT_GUARD_SACM_INFO MSR if system is in Boot Guard boot mode
+ ///
+ MsrValue = (UINT32) AsmReadMsr64 (MSR_BOOT_GUARD_SACM_INFO);
+ DEBUG ((EFI_D_INFO, "MSR_BOOT_GUARD_SACM_INFO MSR = %x\n", MsrValue));
+ if ( (MsrValue & B_NEM_INIT) == 0 ) {
+ DEBUG ((EFI_D_INFO, "NEM is not initiated by Boot Guard ACM\n"));
+ }
+ if (MsrValue & B_MEASURED) {
+ CpuPlatformPolicyPpi->SecurityConfig->BootGuardConfig->MeasuredBoot = TRUE;
+ ///
+ /// if measured bit is set, BIOS needs to bypass startup command
+ ///
+ if (MsrValue & B_TPM_SUCCESS) {
+ CpuPlatformPolicyPpi->SecurityConfig->BootGuardConfig->BypassTpmInit = TRUE;
+ }
+ ///
+ /// Read present TPM type
+ ///
+ CpuPlatformPolicyPpi->SecurityConfig->BootGuardConfig->TpmType = (TPM_TYPE) ( (MsrValue & V_TPM_PRESENT_MASK) >> 1 );
+ DEBUG ((EFI_D_INFO, "TPM Type is %x\n", CpuPlatformPolicyPpi->SecurityConfig->BootGuardConfig->TpmType));
+ }
+ } else {
+ CpuPlatformPolicyPpi->SecurityConfig->BootGuardConfig->BootGuardSupport = FALSE;
+ }
+
+ return;
+}
diff --git a/ReferenceCode/Haswell/CpuInit/Pei/CachePeim.c b/ReferenceCode/Haswell/CpuInit/Pei/CachePeim.c
new file mode 100644
index 0000000..959c58e
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Pei/CachePeim.c
@@ -0,0 +1,1045 @@
+/** @file
+ EFI 2.0 PEIM to initialize the cache and load the BSP microcode
+
+@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 an 'Intel Pre-EFI 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
+
+**/
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGluePeim.h"
+#include "CpuAccess.h"
+#include "CpuInitPeim.h"
+#include EFI_PPI_PRODUCER (Cache)
+#define ALIGNED_SEED 0x01010101
+#endif
+
+INT8
+CheckDirection (
+ IN UINT64 Input
+ );
+
+UINT64
+PeiPower2MaxMemory (
+ IN UINT64 MemoryLength
+ );
+
+VOID
+EfiDisableCacheMtrr (
+ IN UINT64 *OldMtrr
+ );
+
+VOID
+EfiRecoverCacheMtrr (
+ IN BOOLEAN EnableMtrr,
+ IN UINT64 OldMtrr
+ );
+
+VOID
+EfiProgramMtrr (
+ IN PEI_CACHE_PPI *This,
+ IN UINTN MtrrNumber,
+ IN EFI_PHYSICAL_ADDRESS MemoryAddress,
+ IN UINT64 MemoryLength,
+ IN EFI_MEMORY_CACHE_TYPE MemoryCacheType,
+ IN UINT64 ValidMtrrAddressMask
+ );
+
+EFI_STATUS
+EFIAPI
+PeiResetCacheAttributes (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_CACHE_PPI *This
+ );
+
+EFI_STATUS
+EFIAPI
+PeiActivateCache (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_CACHE_PPI *This
+ );
+
+EFI_STATUS
+EFIAPI
+PeiSetCacheAttributes (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_CACHE_PPI *This,
+ IN EFI_PHYSICAL_ADDRESS MemoryAddress,
+ IN UINT64 MemoryLength,
+ IN EFI_MEMORY_CACHE_TYPE MemoryCacheType
+ );
+
+EFI_STATUS
+SearchForExactMtrr (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_CACHE_PPI *This,
+ IN EFI_PHYSICAL_ADDRESS MemoryAddress,
+ IN UINT64 MemoryLength,
+ IN UINT64 ValidMtrrAddressMask,
+ OUT UINT32 *UsedMsrNum,
+ OUT EFI_MEMORY_CACHE_TYPE *MemoryCacheType
+ );
+
+BOOLEAN
+IsDefaultType (
+ IN EFI_MEMORY_CACHE_TYPE MemoryCacheType
+ );
+
+EFI_STATUS
+DisableCacheAsRam (
+ VOID
+ );
+
+typedef struct _ALIGNED_DWORD {
+ UINT32 High;
+ UINT32 Low;
+} ALIGNED_DWORD;
+
+typedef union _ALIGNED {
+ UINT64 AlignedQword;
+ ALIGNED_DWORD AlignedDword;
+} ALIGNED;
+
+typedef struct {
+ UINT32 Msr;
+ UINT32 BaseAddress;
+ UINT32 Length;
+} FIXED_MTRR;
+
+FIXED_MTRR mFixedMtrrTable[] = {
+ {
+ IA32_MTRR_FIX64K_00000,
+ 0,
+ 0x10000
+ },
+ {
+ IA32_MTRR_FIX16K_80000,
+ 0x80000,
+ 0x4000
+ },
+ {
+ IA32_MTRR_FIX16K_A0000,
+ 0xA0000,
+ 0x4000
+ },
+ {
+ IA32_MTRR_FIX4K_C0000,
+ 0xC0000,
+ 0x1000
+ },
+ {
+ IA32_MTRR_FIX4K_C8000,
+ 0xC8000,
+ 0x1000
+ },
+ {
+ IA32_MTRR_FIX4K_D0000,
+ 0xD0000,
+ 0x1000
+ },
+ {
+ IA32_MTRR_FIX4K_D8000,
+ 0xD8000,
+ 0x1000
+ },
+ {
+ IA32_MTRR_FIX4K_E0000,
+ 0xE0000,
+ 0x1000
+ },
+ {
+ IA32_MTRR_FIX4K_E8000,
+ 0xE8000,
+ 0x1000
+ },
+ {
+ IA32_MTRR_FIX4K_F0000,
+ 0xF0000,
+ 0x1000
+ },
+ {
+ IA32_MTRR_FIX4K_F8000,
+ 0xF8000,
+ 0x1000
+ },
+ {
+ 0,
+ 0x100000,
+ 0
+ }
+};
+
+PEI_CACHE_PPI mCachePpi = {
+ PeiSetCacheAttributes,
+ PeiResetCacheAttributes,
+ PeiActivateCache
+};
+
+/**
+ Update MTRR setting to memory buffer
+
+ @param[in] This - Current instance of Pei Cache PPI.
+ @param[in] MsrNum - offset 0-10 maps to Fixed MTRR table
+ offset above 0x200 maps to Variable MTRR table
+ @param[in] UpdateValue - MTRR setting
+ **/
+VOID
+WriteMsrToBuffer (
+ IN PEI_CACHE_PPI *This,
+ IN UINT32 MsrNum,
+ IN UINT64 UpdateValue
+ )
+{
+ CACHE_PPI_INSTANCE *CachePpiInstance;
+ CachePpiInstance = PEI_CACHE_PPI_INSTANCE_FROM_THIS (This);
+ if (MsrNum >= CACHE_VARIABLE_MTRR_BASE) {
+ if ((MsrNum - CACHE_VARIABLE_MTRR_BASE) >= V_MAXIMUM_VARIABLE_MTRR_NUMBER * 2) {
+ ASSERT (FALSE);
+ return;
+ }
+
+ CachePpiInstance->VariableMtrrChanged = TRUE;
+ CachePpiInstance->VariableMtrrValue[MsrNum - CACHE_VARIABLE_MTRR_BASE].Changed = TRUE;
+ CachePpiInstance->VariableMtrrValue[MsrNum - CACHE_VARIABLE_MTRR_BASE].MsrValue = UpdateValue;
+ } else {
+ if (MsrNum >= V_FIXED_MTRR_NUMBER) {
+ ASSERT (FALSE);
+ return;
+ }
+
+ CachePpiInstance->FixedMtrrChanged = TRUE;
+ CachePpiInstance->FixedMtrrValue[MsrNum].Changed = TRUE;
+ CachePpiInstance->FixedMtrrValue[MsrNum].MsrValue = UpdateValue;
+ }
+}
+
+/**
+ Read MTRR from Buffer. If buffer not ready, read from real MSR instead.
+
+ @param[in] This - Current instance of Pei Cache PPI.
+ @param[in] MsrNum - offset 0-10 maps to Fixed MTRR table
+ offset above 0x200 maps to Variable MTRR table
+
+ @retval Return MTRR setting
+ **/
+UINT64
+ReadMsrFromBuffer (
+ IN PEI_CACHE_PPI *This,
+ IN UINT32 MsrNum
+ )
+{
+ UINT64 MtrrVal;
+ CACHE_PPI_INSTANCE *CachePpiInstance;
+ CachePpiInstance = PEI_CACHE_PPI_INSTANCE_FROM_THIS (This);
+ if (MsrNum >= CACHE_VARIABLE_MTRR_BASE) {
+ if ((MsrNum - CACHE_VARIABLE_MTRR_BASE) >= V_MAXIMUM_VARIABLE_MTRR_NUMBER * 2) {
+ ASSERT (FALSE);
+ return 0;
+ }
+
+ if (CachePpiInstance->VariableMtrrValue[MsrNum - CACHE_VARIABLE_MTRR_BASE].Changed) {
+ MtrrVal = CachePpiInstance->VariableMtrrValue[MsrNum - CACHE_VARIABLE_MTRR_BASE].MsrValue;
+ } else {
+ MtrrVal = AsmReadMsr64 (MsrNum);
+ }
+ } else {
+ if (MsrNum >= V_FIXED_MTRR_NUMBER) {
+ ASSERT (FALSE);
+ return 0;
+ }
+
+ if (CachePpiInstance->FixedMtrrValue[MsrNum].Changed) {
+ MtrrVal = CachePpiInstance->FixedMtrrValue[MsrNum].MsrValue;
+ } else {
+ MtrrVal = AsmReadMsr64 (mFixedMtrrTable[MsrNum].Msr);
+ }
+ }
+
+ return MtrrVal;
+}
+
+/**
+ Disable cache and its mtrr
+
+ @param[in] OldMtrr - To return the Old MTRR value
+**/
+VOID
+EfiDisableCacheMtrr (
+ OUT UINT64 *OldMtrr
+ )
+{
+ UINT64 TempQword;
+
+ EfiDisableCache ();
+
+ ///
+ /// Disable Cache MTRR
+ ///
+ *OldMtrr = AsmReadMsr64 (CACHE_IA32_MTRR_DEF_TYPE);
+ TempQword = (*OldMtrr) &~B_CACHE_MTRR_VALID &~B_CACHE_FIXED_MTRR_VALID;
+ AsmWriteMsr64 (CACHE_IA32_MTRR_DEF_TYPE, TempQword);
+ return;
+}
+
+/**
+ Recover cache MTRR
+
+ @param[in] EnableMtrr - Whether to enable the MTRR
+ @param[in] OldMtrr - The saved old MTRR value to restore when not to
+ enable the MTRR
+**/
+VOID
+EfiRecoverCacheMtrr (
+ IN BOOLEAN EnableMtrr,
+ IN UINT64 OldMtrr
+ )
+{
+ UINT64 TempQword;
+
+ TempQword = 0;
+
+ ///
+ /// Enable Cache MTRR
+ ///
+ if (EnableMtrr) {
+ TempQword = AsmReadMsr64 (CACHE_IA32_MTRR_DEF_TYPE);
+ TempQword |= (B_CACHE_MTRR_VALID | B_CACHE_FIXED_MTRR_VALID);
+ } else {
+ TempQword = OldMtrr;
+ }
+
+ AsmWriteMsr64 (CACHE_IA32_MTRR_DEF_TYPE, TempQword);
+
+ EfiEnableCache ();
+ return;
+}
+
+/**
+ Programming MTRR according to Memory address, length, and type.
+
+ @param[in] This - Pointer to PEI_CACHE_PPI
+ @param[in] MtrrNumber - the variable MTRR index number
+ @param[in] MemoryAddress - the address of target memory
+ @param[in] MemoryLength - the length of target memory
+ @param[in] MemoryCacheType - the cache type of target memory
+ @param[in] ValidMtrrAddressMask - the MTRR address mask
+**/
+VOID
+EfiProgramMtrr (
+ IN PEI_CACHE_PPI *This,
+ IN UINT32 MtrrNumber,
+ IN EFI_PHYSICAL_ADDRESS MemoryAddress,
+ IN UINT64 MemoryLength,
+ IN EFI_MEMORY_CACHE_TYPE MemoryCacheType,
+ IN UINT64 ValidMtrrAddressMask
+ )
+{
+ UINT64 TempQword;
+
+ ///
+ /// MTRR Physical Base
+ ///
+ TempQword = (MemoryAddress & ValidMtrrAddressMask) | MemoryCacheType;
+ WriteMsrToBuffer (This, MtrrNumber, TempQword);
+
+ ///
+ /// MTRR Physical Mask
+ ///
+ TempQword = ~(MemoryLength - 1);
+ WriteMsrToBuffer (This, MtrrNumber + 1, (TempQword & ValidMtrrAddressMask) | B_CACHE_MTRR_VALID);
+
+ return;
+}
+
+/**
+ Calculate max memory of power 2
+
+ @param[in] MemoryLength - Memory length that will be calculated
+
+ @retval Max memory
+**/
+UINT64
+PeiPower2MaxMemory (
+ IN UINT64 MemoryLength
+ )
+{
+ UINT64 Result;
+ UINT32 *ResultPointer;
+ UINT32 *MemoryLengthPointer;
+ MemoryLengthPointer = (UINT32 *) &MemoryLength;
+ ResultPointer = (UINT32 *) &Result;
+ Result = 0;
+ if (MemoryLengthPointer[1] != 0) {
+ ResultPointer[1] = GetPowerOfTwo32 (MemoryLengthPointer[1]);
+ } else {
+ ResultPointer[0] = GetPowerOfTwo32 (MemoryLengthPointer[0]);
+ }
+
+ return Result;
+}
+
+/**
+ Program the unaligned MTRR register.
+
+ @param[in] This - Pointer to PEI_CACHE_PPI
+ @param[in] AlignedQword - The aligned 64-bit cache type.
+ @param[in] MsrNum - The index of current MTRR.
+ @param[in] UnalignedBase - Base Address of the current unaligned MTRR.
+ @param[in] UnalignedLimit - Limit Address of the current unaligned MTRR.
+
+ @retval EFI_SUCCESS - The unaligned MTRR is set successfully.
+ @retval EFI_DEVICE_ERROR - The unaligned address is not the multiple of the basic length of MTRR.
+**/
+EFI_STATUS
+PeiProgramUnalignedMtrr (
+ IN PEI_CACHE_PPI *This,
+ IN UINT64 AlignedQword,
+ IN UINTN MsrNum,
+ IN UINT32 UnalignedBase,
+ IN UINT32 UnalignedLimit
+ )
+{
+ UINT32 UnalignedOffset;
+ UINT64 TempQword;
+ UINT64 Mask;
+ UINT8 ByteShift;
+
+ UnalignedOffset = UnalignedBase - mFixedMtrrTable[MsrNum].BaseAddress;
+ if (UnalignedOffset % mFixedMtrrTable[MsrNum].Length != 0) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ ByteShift = (UINT8) (UnalignedOffset / mFixedMtrrTable[MsrNum].Length);
+ Mask = ~(LShiftU64 (1, ByteShift * 8) - 1);
+
+ if (UnalignedLimit < mFixedMtrrTable[MsrNum + 1].BaseAddress) {
+ UnalignedOffset = UnalignedLimit - mFixedMtrrTable[MsrNum].BaseAddress;
+ if (UnalignedOffset % mFixedMtrrTable[MsrNum].Length != 0) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ ByteShift = (UINT8) (UnalignedOffset / mFixedMtrrTable[MsrNum].Length);
+ Mask &= LShiftU64 (1, ByteShift * 8) - 1;
+ }
+
+ TempQword = ReadMsrFromBuffer (This, MsrNum) &~Mask;
+ TempQword |= AlignedQword & Mask;
+ WriteMsrToBuffer (This, MsrNum, TempQword);
+ return EFI_SUCCESS;
+}
+
+/**
+ Given the low memory range ( <= 1MB) and cache type, program the MTRRs.
+
+ @param[in] This - Current instance of Pei Cache PPI.
+ @param[in] MemoryCacheType - Cache Type.
+ @param[in] MemoryBase - Base Address of Memory to program MTRR.
+ @param[in] MemoryLimit - Limit Address of Memory to program MTRR.
+
+ @retval EFI_SUCCESS - Low memory MTRR is set successfully.
+ @retval others - An error occurs when setting Low memory MTRR.
+**/
+EFI_STATUS
+PeiProgramLowMemoryMtrr (
+ IN PEI_CACHE_PPI *This,
+ IN EFI_MEMORY_CACHE_TYPE MemoryCacheType,
+ IN UINT32 MemoryBase,
+ IN UINT32 MemoryLimit
+ )
+{
+ EFI_STATUS Status;
+ ALIGNED Aligned;
+ UINTN MsrNum;
+
+ Status = EFI_SUCCESS;
+
+ Aligned.AlignedDword.High = MemoryCacheType * ALIGNED_SEED;
+ Aligned.AlignedDword.Low = Aligned.AlignedDword.High;
+
+ for (MsrNum = 0; mFixedMtrrTable[MsrNum].BaseAddress < MemoryBase; MsrNum++) {
+ ;
+ }
+
+ if (MemoryBase < mFixedMtrrTable[MsrNum].BaseAddress) {
+ Status = PeiProgramUnalignedMtrr (This, Aligned.AlignedQword, MsrNum - 1, MemoryBase, MemoryLimit);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ }
+
+ while (MsrNum < V_FIXED_MTRR_NUMBER && MemoryLimit >= mFixedMtrrTable[MsrNum + 1].BaseAddress) {
+ ///
+ /// Program aligned MTRR
+ ///
+ WriteMsrToBuffer (This, MsrNum, Aligned.AlignedQword);
+ MsrNum++;
+ }
+
+ if (MemoryLimit > mFixedMtrrTable[MsrNum].BaseAddress) {
+ Status = PeiProgramUnalignedMtrr (
+ This,
+ Aligned.AlignedQword,
+ MsrNum,
+ mFixedMtrrTable[MsrNum].BaseAddress,
+ MemoryLimit
+ );
+ }
+
+Done:
+ return Status;
+}
+
+/**
+ Given the memory range and cache type, programs the MTRRs.
+
+ @param[in] PeiServices - General purpose services available to every PEIM.
+ @param[in] This - Current instance of Pei Cache PPI.
+ @param[in] MemoryAddress - Base Address of Memory to program MTRR.
+ @param[in] MemoryLength - Length of Memory to program MTRR.
+ @param[in] MemoryCacheType - Cache Type.
+
+ @retval EFI_SUCCESS - Mtrr are set successfully.
+ @retval EFI_LOAD_ERROR - No empty MTRRs to use.
+ @retval EFI_INVALID_PARAMETER - The input parameter is not valid.
+ @retval others - An error occurs when setting MTTR.
+**/
+EFI_STATUS
+EFIAPI
+PeiSetCacheAttributes (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_CACHE_PPI *This,
+ IN EFI_PHYSICAL_ADDRESS MemoryAddress,
+ IN UINT64 MemoryLength,
+ IN EFI_MEMORY_CACHE_TYPE MemoryCacheType
+ )
+{
+ EFI_STATUS Status;
+ UINT32 MsrNum;
+ UINT64 TempQword;
+ UINT32 UsedMsrNum;
+ EFI_MEMORY_CACHE_TYPE UsedMemoryCacheType;
+ UINT64 ValidMtrrAddressMask;
+ EFI_CPUID_REGISTER FeatureInfo;
+ UINT64 Power2Length[8];
+ UINT64 LengthArray[8];
+ UINTN LengthSize;
+ UINTN Index;
+ UINTN Count;
+ UINT32 Remainder;
+ UINT32 VariableMtrrLimit;
+ UINT32 *TempQwordPointer;
+ UINT32 *Power2LengthPointer;
+
+ TempQwordPointer = (UINT32 *) &TempQword;
+
+ VariableMtrrLimit = (UINT32) (AsmReadMsr64 (IA32_MTRR_CAP) & B_IA32_MTRR_VARIABLE_SUPPORT);
+ if (VariableMtrrLimit > V_MAXIMUM_VARIABLE_MTRR_NUMBER) {
+ VariableMtrrLimit = V_MAXIMUM_VARIABLE_MTRR_NUMBER;
+ }
+ ValidMtrrAddressMask = 0x1000000000ULL;
+
+ AsmCpuid (
+ CPUID_EXTENDED_FUNCTION,
+ &FeatureInfo.RegEax,
+ &FeatureInfo.RegEbx,
+ &FeatureInfo.RegEcx,
+ &FeatureInfo.RegEdx
+ );
+ if (FeatureInfo.RegEax >= CPUID_VIR_PHY_ADDRESS_SIZE) {
+ AsmCpuid (
+ CPUID_VIR_PHY_ADDRESS_SIZE,
+ &FeatureInfo.RegEax,
+ &FeatureInfo.RegEbx,
+ &FeatureInfo.RegEcx,
+ &FeatureInfo.RegEdx
+ );
+ ValidMtrrAddressMask = (LShiftU64 ((UINT64) 1, FeatureInfo.RegEax & 0xFF) - 1) & (~(UINT64) 0x0FFF);
+ }
+
+ ///
+ /// Check for invalid parameter
+ ///
+ if ((MemoryAddress &~ValidMtrrAddressMask) != 0 || (MemoryLength &~ValidMtrrAddressMask) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (MemoryCacheType) {
+ case EfiCacheTypeUncacheable:
+ case EfiCacheTypeWriteCombining:
+ case EfiCacheTypeWriteThrough:
+ case EfiCacheTypeWriteProtected:
+ case EfiCacheTypeWriteBack:
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ///
+ /// Check if Fixed MTRR
+ ///
+ if ((MemoryAddress + MemoryLength) <= (1 << 20)) {
+ Status = PeiProgramLowMemoryMtrr (
+ This,
+ MemoryCacheType,
+ (UINT32) MemoryAddress,
+ (UINT32) (MemoryAddress + MemoryLength)
+ );
+ return Status;
+ }
+
+ ///
+ /// Special case for 1 MB base address
+ ///
+ if (MemoryAddress == 0x100000) {
+ MemoryAddress = 0;
+ MemoryLength += 0x100000;
+ }
+
+ ///
+ /// Split MemoryLength into a sum of power of 2
+ ///
+ ZeroMem (Power2Length, sizeof (Power2Length));
+ LengthSize = 0;
+ TempQword = MemoryLength;
+ do {
+ Power2Length[LengthSize] = PeiPower2MaxMemory (TempQword);
+ TempQword -= Power2Length[LengthSize];
+ LengthSize++;
+ } while (TempQword != 0 && LengthSize < 8);
+ if (TempQword != 0) {
+ return EFI_LOAD_ERROR;
+ }
+
+ ///
+ /// Work out an order of splitted power of 2
+ /// so that Base and Length are suitable for MTRR
+ /// setting constraints.
+ ///
+ Count = 0;
+ TempQword = MemoryAddress;
+ do {
+ for (Index = 0; Index < LengthSize; Index++) {
+ Power2LengthPointer = (UINT32 *) &Power2Length[Index];
+ if (Power2Length[Index] != 0) {
+ if (Power2LengthPointer[1] != 0) {
+ Remainder = (UINT32) TempQword;
+ if (Remainder == 0) {
+ DivU64x32Remainder (
+ TempQwordPointer[1],
+ Power2LengthPointer[1],
+ &Remainder
+ );
+ }
+ } else {
+ DivU64x32Remainder (TempQword, (UINT32) Power2Length[Index], &Remainder);
+ }
+
+ if (Remainder == 0) {
+ LengthArray[Count] = Power2Length[Index];
+ TempQword += Power2Length[Index];
+ Power2Length[Index] = 0;
+ Count++;
+ break;
+ }
+ }
+ }
+
+ if (Index == LengthSize) {
+ return EFI_LOAD_ERROR;
+ }
+ } while (Count < LengthSize);
+ ///
+ /// Begin setting the MTRR according to the order
+ ///
+ for (Index = 0; Index < LengthSize; Index++, MemoryAddress += MemoryLength) {
+ MemoryLength = LengthArray[Index];
+ ///
+ /// Search if the range attribute has been set before
+ ///
+ Status = SearchForExactMtrr (
+ PeiServices,
+ This,
+ MemoryAddress,
+ MemoryLength,
+ ValidMtrrAddressMask,
+ &UsedMsrNum,
+ &UsedMemoryCacheType
+ );
+
+ if (!EFI_ERROR (Status)) {
+ ///
+ /// Compare if it has the same type as current setting
+ ///
+ if (UsedMemoryCacheType != MemoryCacheType) {
+ ///
+ /// Different type
+ ///
+ ///
+ /// Check if the set type is the same as default type
+ ///
+ if (IsDefaultType (MemoryCacheType)) {
+ ///
+ /// Clear the mtrr
+ ///
+ WriteMsrToBuffer (This, UsedMsrNum, 0);
+ WriteMsrToBuffer (This, UsedMsrNum + 1, 0);
+
+ } else {
+ ///
+ /// Modify the mtrr type
+ ///
+ EfiProgramMtrr (
+ This,
+ UsedMsrNum,
+ MemoryAddress,
+ MemoryLength,
+ MemoryCacheType,
+ ValidMtrrAddressMask
+ );
+ }
+ }
+
+ continue;
+ }
+
+ ///
+ /// Find first unused MTRR
+ ///
+ for (MsrNum = CACHE_VARIABLE_MTRR_BASE; MsrNum < (CACHE_VARIABLE_MTRR_BASE + VariableMtrrLimit * 2); MsrNum += 2) {
+ if (ReadMsrFromBuffer (This, MsrNum + 1) == 0) {
+ break;
+ }
+ }
+ ///
+ /// Check if we ran out of variable-range MTRRs
+ ///
+ if (MsrNum >= (CACHE_VARIABLE_MTRR_BASE + VariableMtrrLimit * 2)) {
+ return EFI_LOAD_ERROR;
+ }
+
+ EfiProgramMtrr (
+ This,
+ MsrNum,
+ MemoryAddress,
+ MemoryLength,
+ MemoryCacheType,
+ ValidMtrrAddressMask
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Update MTRR setting from buffer to MSR. Disable NEM when NEM is not disabled yet.
+
+ @param[in] PeiServices - General purpose services available to every PEIM.
+ @param[in] This - Current instance of Pei Cache PPI.
+
+ @retval EFI_SUCCESS - Mtrr are set successfully.
+**/
+EFI_STATUS
+EFIAPI
+PeiActivateCache (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_CACHE_PPI *This
+ )
+{
+ UINT32 VariableMtrrLimit;
+ UINT32 MsrNum;
+ UINT64 OldMtrr;
+ UINT16 Index;
+ CACHE_PPI_INSTANCE *CachePpiInstance;
+ CachePpiInstance = PEI_CACHE_PPI_INSTANCE_FROM_THIS (This);
+
+ VariableMtrrLimit = (UINT32) (AsmReadMsr64 (IA32_MTRR_CAP) & B_IA32_MTRR_VARIABLE_SUPPORT);
+ if (VariableMtrrLimit > V_MAXIMUM_VARIABLE_MTRR_NUMBER) {
+ VariableMtrrLimit = V_MAXIMUM_VARIABLE_MTRR_NUMBER;
+ }
+
+ ///
+ /// Disable NEM when NEM is not disabled yet
+ ///
+ if (!CachePpiInstance->NemDisabledDone) {
+ DisableCacheAsRam ();
+ CachePpiInstance->NemDisabledDone = TRUE;
+ }
+
+ ///
+ /// Disable/Enable cache only when MTRR configuration is changed in MTRR buffer
+ ///
+ if (CachePpiInstance->FixedMtrrChanged || CachePpiInstance->VariableMtrrChanged) {
+ EfiDisableCacheMtrr (&OldMtrr);
+ if (CachePpiInstance->FixedMtrrChanged) {
+ for (Index = 0; Index < V_FIXED_MTRR_NUMBER; Index++) {
+ if (CachePpiInstance->FixedMtrrValue[Index].Changed) {
+ AsmWriteMsr64 (mFixedMtrrTable[Index].Msr, CachePpiInstance->FixedMtrrValue[Index].MsrValue);
+ CachePpiInstance->FixedMtrrValue[Index].Changed = FALSE;
+ }
+ }
+
+ CachePpiInstance->FixedMtrrChanged = FALSE;
+ }
+
+ if (CachePpiInstance->VariableMtrrChanged) {
+ for (MsrNum = CACHE_VARIABLE_MTRR_BASE; MsrNum < (CACHE_VARIABLE_MTRR_BASE + VariableMtrrLimit * 2); MsrNum++) {
+ if (CachePpiInstance->VariableMtrrValue[MsrNum - CACHE_VARIABLE_MTRR_BASE].Changed) {
+ AsmWriteMsr64 (MsrNum, CachePpiInstance->VariableMtrrValue[MsrNum - CACHE_VARIABLE_MTRR_BASE].MsrValue);
+ CachePpiInstance->VariableMtrrValue[MsrNum - CACHE_VARIABLE_MTRR_BASE].Changed = FALSE;
+ }
+
+ CachePpiInstance->VariableMtrrChanged = FALSE;
+ }
+ }
+
+ EfiRecoverCacheMtrr (TRUE, OldMtrr);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Reset all the MTRRs to a known state.
+
+ @param[in] PeiServices - General purpose services available to every PEIM.
+ @param[in] This - Pointer to the instance of the PEI_CACHE_PPI.
+
+ @retval EFI_SUCCESS - All MTRRs have been reset successfully.
+**/
+EFI_STATUS
+EFIAPI
+PeiResetCacheAttributes (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_CACHE_PPI *This
+ )
+{
+ UINT32 MsrNum;
+ UINT16 Index;
+ UINT32 VariableMtrrLimit;
+
+ VariableMtrrLimit = (UINT32) (AsmReadMsr64 (IA32_MTRR_CAP) & B_IA32_MTRR_VARIABLE_SUPPORT);
+ if (VariableMtrrLimit > V_MAXIMUM_VARIABLE_MTRR_NUMBER) {
+ VariableMtrrLimit = V_MAXIMUM_VARIABLE_MTRR_NUMBER;
+ }
+
+ Index = 0;
+
+ ///
+ /// Reset Fixed Mtrrs
+ ///
+ while (mFixedMtrrTable[Index].Msr != 0) {
+ WriteMsrToBuffer (This, Index, 0);
+ Index++;
+ }
+
+ ///
+ /// Reset Variable Mtrrs
+ ///
+ for (MsrNum = CACHE_VARIABLE_MTRR_BASE; MsrNum < (CACHE_VARIABLE_MTRR_BASE + VariableMtrrLimit * 2); MsrNum++) {
+ WriteMsrToBuffer (This, MsrNum, 0);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Search the memory cache type for specific memory from MTRR.
+
+ @param[in] PeiServices - General purpose services available to every PEIM.
+ @param[in] This - Current instance of Pei Cache PPI.
+ @param[in] MemoryAddress - the address of target memory
+ @param[in] MemoryLength - the length of target memory
+ @param[in] ValidMtrrAddressMask - the MTRR address mask
+ @param[in] UsedMsrNum - the used MSR number
+ @param[in] UsedMemoryCacheType - the cache type for the target memory
+
+ @retval EFI_SUCCESS - The memory is found in MTRR and cache type is returned
+ @retval EFI_NOT_FOUND - The memory is not found in MTRR
+**/
+EFI_STATUS
+SearchForExactMtrr (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_CACHE_PPI *This,
+ IN EFI_PHYSICAL_ADDRESS MemoryAddress,
+ IN UINT64 MemoryLength,
+ IN UINT64 ValidMtrrAddressMask,
+ OUT UINT32 *UsedMsrNum,
+ OUT EFI_MEMORY_CACHE_TYPE *UsedMemoryCacheType
+ )
+{
+ UINT32 MsrNum;
+ UINT64 TempQword;
+ UINT32 VariableMtrrLimit;
+
+ VariableMtrrLimit = (UINT32) (AsmReadMsr64 (IA32_MTRR_CAP) & B_IA32_MTRR_VARIABLE_SUPPORT);
+ if (VariableMtrrLimit > V_MAXIMUM_VARIABLE_MTRR_NUMBER) {
+ VariableMtrrLimit = V_MAXIMUM_VARIABLE_MTRR_NUMBER;
+ }
+
+ for (MsrNum = CACHE_VARIABLE_MTRR_BASE; MsrNum < (CACHE_VARIABLE_MTRR_BASE + VariableMtrrLimit * 2 - 1); MsrNum += 2) {
+
+ TempQword = ReadMsrFromBuffer (This, MsrNum + 1);
+
+ if ((TempQword & B_CACHE_MTRR_VALID) == 0) {
+ continue;
+ }
+
+ if ((TempQword & ValidMtrrAddressMask) != ((~(MemoryLength - 1)) & ValidMtrrAddressMask)) {
+ continue;
+ }
+
+ TempQword = ReadMsrFromBuffer (This, MsrNum);
+
+ if ((TempQword & ValidMtrrAddressMask) != (MemoryAddress & ValidMtrrAddressMask)) {
+ continue;
+ }
+
+ *UsedMemoryCacheType = (EFI_MEMORY_CACHE_TYPE) (TempQword & 0xFF);
+ *UsedMsrNum = MsrNum;
+
+ return EFI_SUCCESS;
+
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Compares provided Cache type to default type
+
+ @param[in] MemoryCacheType - Memory type for testing
+
+ @retval TRUE - Memory type instance is the default type
+ @retval FALSE - Memory type instance is not the default type
+**/
+BOOLEAN
+IsDefaultType (
+ IN EFI_MEMORY_CACHE_TYPE MemoryCacheType
+ )
+{
+
+ if ((AsmReadMsr64 (CACHE_IA32_MTRR_DEF_TYPE) & 0xFF) != MemoryCacheType) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+/**
+ Install CacheInitPpi
+
+ @retval EFI_OUT_OF_RESOURCES - failed to allocate required pool
+**/
+EFI_STATUS
+CacheInitPpiInit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ CACHE_PPI_INSTANCE *CachePpiInstance;
+
+ CachePpiInstance = AllocateZeroPool (sizeof (CACHE_PPI_INSTANCE));
+ ASSERT (CachePpiInstance != NULL);
+ if (CachePpiInstance == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CachePpiInstance->Ppi.SetCache = PeiSetCacheAttributes;
+ CachePpiInstance->Ppi.ResetCache = PeiResetCacheAttributes;
+ CachePpiInstance->Ppi.ActivateCache = PeiActivateCache;
+
+ CachePpiInstance->PpiDesc.Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
+ CachePpiInstance->PpiDesc.Guid = &gPeiCachePpiGuid;
+ CachePpiInstance->PpiDesc.Ppi = &CachePpiInstance->Ppi;
+
+ ///
+ /// Install PPI
+ ///
+ Status = PeiServicesInstallPpi (&CachePpiInstance->PpiDesc);
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+VOID
+CacheInvd (
+ VOID
+ );
+
+/**
+ Disable NEM (cache-as-ram)
+
+ @retval EFI_SUCCESS - always return success
+**/
+EFI_STATUS
+DisableCacheAsRam (
+ VOID
+ )
+{
+ UINT64 CacheAsRamMsr;
+ UINT64 McStatus;
+ UINT32 McIndex;
+ UINT32 McCounter;
+ UINT64 TempQword;
+ UINT64 OldMtrr;
+
+ CacheAsRamMsr = AsmReadMsr64 (NO_EVICT_MODE);
+
+ ///
+ /// Check if CAR has already been disabled. We should not
+ /// execute CacheInvd() after cache has been enabled. This
+ /// check will avoid that.
+ ///
+ if ((CacheAsRamMsr & B_NO_EVICT_MODE_RUN) == 0) {
+ return EFI_SUCCESS;
+ }
+
+ CacheInvd ();
+
+ ///
+ /// Step 3: Disable No-Eviction Mode Run State by clearing
+ /// NO_EVICT_MODE MSR 2E0h bit [1] = 0
+ ///
+ CacheAsRamMsr &= ~B_NO_EVICT_MODE_RUN;
+ AsmWriteMsr64 (NO_EVICT_MODE, CacheAsRamMsr);
+
+ ///
+ /// Step 4: Disable No-Eviction Mode Setup State by clearing
+ /// NO_EVICT_MODE MSR 2E0h bit [0] = 0
+ ///
+ CacheAsRamMsr &= ~B_NO_EVICT_MODE_SETUP;
+ AsmWriteMsr64 (NO_EVICT_MODE, CacheAsRamMsr);
+
+ ///
+ /// Disable Cache MTRR by cleaning IA32_MTRR_DEF_TYPE.E or IA32_MTRR_DEF_TYPE.GE
+ ///
+ OldMtrr = AsmReadMsr64 (CACHE_IA32_MTRR_DEF_TYPE);
+ TempQword = OldMtrr &~B_CACHE_MTRR_VALID;
+ AsmWriteMsr64 (CACHE_IA32_MTRR_DEF_TYPE, TempQword);
+
+ ///
+ /// After NEM is disabled, BIOS must clear any Machine Check Bank 5-8 errors that may
+ /// have occurred as the result of ... MLC to to LLC Evictions.
+ ///
+ McStatus = 0;
+ McCounter = (UINT32) (AsmReadMsr64 (IA32_MCG_CAP) & 0x0f);
+ for (McIndex = 5; McIndex < McCounter; McIndex++) {
+ if (McIndex <= 8) {
+ AsmWriteMsr64 (IA32_MC0_STATUS + McIndex * 4, McStatus);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/ReferenceCode/Haswell/CpuInit/Pei/CpuInitPei.cif b/ReferenceCode/Haswell/CpuInit/Pei/CpuInitPei.cif
new file mode 100644
index 0000000..f69c12f
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Pei/CpuInitPei.cif
@@ -0,0 +1,20 @@
+<component>
+ name = "CpuInitPei"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\CpuInit\Pei"
+ RefName = "CpuInitPei"
+[files]
+"CpuInitPeim.c"
+"CachePeim.c"
+"CpuInitPeim.h"
+"PfatInit.c"
+"PfatInit.h"
+"CpuOcInit.c"
+"CpuOcInit.h"
+"CpuInitPeim.dxs"
+"CpuInitPeim.inf"
+"CpuInitPei.mak"
+"CpuInitPei.sdl"
+"Ia32\Cpu.asm"
+"BootGuardInit.c"
+<endComponent>
diff --git a/ReferenceCode/Haswell/CpuInit/Pei/CpuInitPei.mak b/ReferenceCode/Haswell/CpuInit/Pei/CpuInitPei.mak
new file mode 100644
index 0000000..7258a7c
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Pei/CpuInitPei.mak
@@ -0,0 +1,76 @@
+# MAK file for the eModule:PowerManagement
+
+EDK : CpuInitPei
+
+BUILD_CpuInitPei_DIR = $(BUILD_DIR)\$(CpuInitPei_DIR)
+
+$(BUILD_DIR)\CpuInitPei.mak : $(CpuInitPei_DIR)\CpuInitPei.cif $(BUILD_RULES)
+ $(CIF2MAK) $(CpuInitPei_DIR)\CpuInitPei.cif $(CIF2MAK_DEFAULTS)
+
+CpuInitPei : $(BUILD_DIR)\CpuInitPei.MAK CpuInitPeiBin
+
+CpuInitPei_OBJECTS = \
+ $(BUILD_CpuInitPei_DIR)\CpuInitPeim.obj \
+ $(BUILD_CpuInitPei_DIR)\CachePeim.obj \
+ $(BUILD_CpuInitPei_DIR)\CpuOcInit.obj \
+ $(BUILD_CpuInitPei_DIR)\PfatInit.obj \
+ $(BUILD_CpuInitPei_DIR)\ia32\Cpu.obj \
+ $(BUILD_CpuInitPei_DIR)\BootGuardInit.obj
+
+CpuInitPei_MY_INCLUDES= \
+ $(EDK_INCLUDES)\
+ $(PROJECT_CPU_INCLUDES)\
+ $(INTEL_MCH_INCLUDES)\
+ $(ME_INCLUDES)\
+ $(INTEL_PCH_INCLUDES)
+
+CpuInitPei_DEFINES = $(MY_DEFINES)\
+ /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=PeimInitializeCpu"\
+ /D __EDKII_GLUE_BASE_LIB__ \
+ /D __EDKII_GLUE_PEI_MEMORY_ALLOCATION_LIB__ \
+ /D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ \
+ /D __EDKII_GLUE_PEI_SERVICES_TABLE_POINTER_LIB_MM7__ \
+
+CpuInitPei_LIBS =\
+ $(CPU_PPI_LIB)\
+ $(CPUIA32LIB)\
+ $(EdkIIGluePeiServicesLib_LIB) \
+ $(EdkIIGluePeiReportStatusCodeLib_LIB) \
+ $(EfiRuntimeLib_LIB)\
+ $(INTEL_PCH_PROTOCOL_LIB)\
+ $(EFIRUNTIMELIB)\
+ $(EDKFRAMEWORKPPILIB) \
+ $(EdkIIGluePeiMemoryAllocationLib_LIB)\
+ $(EdkIIGluePeiDebugLibReportStatusCode_LIB)\
+ $(BUILD_DIR)\IA32\EdkIIGlueBaseLib.lib\
+ $(IntelPchPpiLib_LIB)\
+ $(EdkIIGlueBaseLibIA32_LIB)\
+ $(EdkIIGluePeiHobLib_LIB) \
+ $(CpuGuidLib_LIB) \
+ $(PEIHOBLIB) \
+ $(EdkIIGlueBaseIoLibIntrinsic_LIB)\
+ $(EdkIIGlueBasePciLibPciExpress_LIB) \
+ $(EdkIIGlueBasePciExpressLib_LIB)\
+ $(PchPlatformPeiLib_LIB)\
+ $(CpuPlatformLib_LIB)\
+ $(OcPlatformLib_LIB)\
+ $(MeLibPpi_LIB)\
+ $(BootGuardLib_LIB)\
+ $(EFISCRIPTLIB)
+
+CpuInitPeiBin : $(CpuInitPei_LIBS) $(HeciPei_LIBS)
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\CpuInitPei.mak all\
+ NAME=CpuInitPei\
+ MAKEFILE=$(BUILD_DIR)\CpuInitPei.mak \
+ "MY_INCLUDES=$(CpuInitPei_MY_INCLUDES)" \
+ "MY_DEFINES=$(CpuInitPei_DEFINES)"\
+ OBJECTS="$(CpuInitPei_OBJECTS)" \
+ GUID=01359D99-9446-456d-ADA4-50A711C03ADA\
+ ENTRY_POINT=_ModuleEntryPoint \
+ TYPE=PEIM \
+ EDKIIModule=PEIM\
+ DEPEX1=$(CpuInitPei_DIR)\CpuInitPeim.DXS \
+ DEPEX1_TYPE=EFI_SECTION_PEI_DEPEX \
+ COMPRESS=0
+#-----------------------------------------------------------------------
diff --git a/ReferenceCode/Haswell/CpuInit/Pei/CpuInitPei.sdl b/ReferenceCode/Haswell/CpuInit/Pei/CpuInitPei.sdl
new file mode 100644
index 0000000..a1abd10
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Pei/CpuInitPei.sdl
@@ -0,0 +1,37 @@
+TOKEN
+ Name = "CpuInitPei_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable Cpu Pei init support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+End
+
+PATH
+ Name = "CpuInitPei_DIR"
+End
+
+MODULE
+ Help = "Includes CpuInitPei.mak to Project"
+ File = "CpuInitPei.mak"
+End
+
+ELINK
+ Name = "CpuInitPei_INCLUDES"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "/I$(CpuInitPei_DIR)"
+ Parent = "CpuInitPei_INCLUDES"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\CpuInitPei.ffs"
+ Parent = "FV_BB"
+ InvokeOrder = AfterParent
+End
+
diff --git a/ReferenceCode/Haswell/CpuInit/Pei/CpuInitPeim.c b/ReferenceCode/Haswell/CpuInit/Pei/CpuInitPeim.c
new file mode 100644
index 0000000..739e043
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Pei/CpuInitPeim.c
@@ -0,0 +1,1404 @@
+/** @file
+ EFI 2.0 PEIM to initialize the cache and program for unlock processor
+
+Revision History
+
+@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 an 'Intel Pre-EFI 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
+
+**/
+
+///
+/// External include files do NOT need to be explicitly specified in real EDKII
+/// environment
+///
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGluePeim.h"
+#include "CpuAccess.h"
+#include "CpuInitPeim.h"
+#include "PchAccess.h"
+#include "SaAccess.h"
+#include "PfatInit.h"
+#include "CpuOcInit.h"
+#include "CpuPlatformLib.h"
+
+#include EFI_PPI_DEFINITION (BootMode)
+#include EFI_PPI_DEFINITION (PchInit)
+#include EFI_PPI_CONSUMER (PchReset)
+#endif
+
+#include EFI_PPI_CONSUMER (SecPlatformInformation)
+#include EFI_GUID_DEFINITION (HtBistHob)
+
+/**
+ This fuction compare Setup Options of ActiveCores & HyperThreading against the CPU Strap
+ and in case of mismatch requests reset
+
+ @param[in] PeiServices - For printouts
+ @param[in] CpuStrapSet - Strap current setting
+ @param[in] CpuPlatformPolicyPpi - Platform Policy PPI
+
+ @retval CPU_RESET_TYPE
+ @retval CPU_ONLY_RESET - if reset is needed
+ @retval NO_RESET - otherwise
+**/
+CPU_RESET_TYPE
+SetActiveCoresAndSmtEnableDisable (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN CPU_STRAP_SET *CpuStrapSet,
+ IN PEI_CPU_PLATFORM_POLICY_PPI *CpuPlatformPolicyPpi
+ )
+{
+ CPU_RESET_TYPE ResetType;
+ UINT16 TotalThreadsPerCore;
+ UINT32 Data32;
+ UINT32 NumberOfActiveCores;
+ UINT32 NumberOfActiveThreads;
+ EFI_CPUID_REGISTER Cpuid0B = { 0, 0, 0, 0 };
+
+ ResetType = NO_RESET;
+
+ ///
+ /// Read CPUID(0xB) with ECX=0 for number of logical processors per Core.
+ /// This value does NOT change based on Intel HT Technology disable and core disables.
+ ///
+ Cpuid0B.RegEcx = 0;
+ AsmCpuidEx (CPUID_PROCESSOR_TOPOLOGY, 0, NULL, &Cpuid0B.RegEbx, NULL, NULL);
+ TotalThreadsPerCore = (UINT16) Cpuid0B.RegEbx;
+
+ ///
+ /// CORE_THREAD_COUNT - msr 0x35
+ /// Symbol Name MSB:LSB Description
+ /// CoreCount CoreCount 31:16 The Core Count reflects the enabled cores based
+ /// on the above thread count and the value of threads_
+ /// available (to determine if HT is on) at reset time.
+ ///
+ /// ThreadCount ThreadCount 15:0 The Thread Count reflects the enabled threads based
+ /// on the factory-configured thread count and the value
+ /// of the CSR_DESIRED_CORES register at reset time.
+ ///
+ ///
+ /// Read MSR for Active Core and Thread Count.
+ ///
+ Data32 = (UINT32) AsmReadMsr64 (MSR_CORE_THREAD_COUNT);
+ NumberOfActiveCores = (UINT32) ((Data32 >> 16) & 0xFFFF);
+ NumberOfActiveThreads = (UINT32) (Data32 & 0xFFFF);
+
+ DEBUG ((EFI_D_INFO, "Number of Active Cores / Threads = %x / %x\n", NumberOfActiveCores, NumberOfActiveThreads));
+
+ if (TotalThreadsPerCore > 1) {
+ ///
+ /// SMT is supported
+ ///
+ DEBUG ((EFI_D_INFO, "SMT is supported\n"));
+ ///
+ /// Check if the configuration of SMT matches the BIOS Setup option.
+ ///
+ if (CpuStrapSet->HtDisabled == CpuPlatformPolicyPpi->CpuConfig->HyperThreading) {
+ ///
+ /// SMT configuration doesn't match BIOS Setup option; update the Strap Set Data and Issue a Warm reset
+ ///
+ DEBUG ((EFI_D_INFO, "SMT configuration doesn't match the setup value\n"));
+ CpuStrapSet->HtDisabled = !CpuPlatformPolicyPpi->CpuConfig->HyperThreading;
+ ResetType |= WARM_RESET;
+ }
+ } else {
+ ///
+ /// SMT is not supported by default fusing.
+ ///
+ DEBUG ((EFI_D_WARN, "SMT is NOT supported\n"));
+ CpuStrapSet->HtDisabled = 1;
+ CpuPlatformPolicyPpi->CpuConfig->HyperThreading = CPU_FEATURE_DISABLE;
+ }
+ ///
+ /// Check if the configuration of "Active Core" matches the BIOS Setup option.
+ ///
+ if (CpuStrapSet->NumberOfActiveCores != CpuPlatformPolicyPpi->CpuConfig->ActiveCoreCount) {
+ DEBUG (
+ (EFI_D_INFO,
+ "NumberOfActiveCores doesn't match the value from Setup = %x / %x\n",
+ CpuStrapSet->NumberOfActiveCores,
+ CpuPlatformPolicyPpi->CpuConfig->ActiveCoreCount)
+ );
+ CpuStrapSet->NumberOfActiveCores = CpuPlatformPolicyPpi->CpuConfig->ActiveCoreCount;
+ ///
+ /// Haswell CPU doesnt require COLD reset to set number of active cores
+ ///
+ ResetType |= WARM_RESET;
+ }
+
+ return ResetType;
+}
+
+/**
+ This fuction compare Setup Options of BIST against the CPU Strap
+ and in case of mismatch requests reset
+
+ @param[in] PeiServices - For printouts
+ @param[in] CpuStrapSet - Strap current setting
+ @param[in] CpuPlatformPolicyPpi - Platform Policy PPI
+
+ @retval CPU_RESET_TYPE
+ @retval CPU_ONLY_RESET - if reset is needed
+ @retval NO_RESET - otherwise
+**/
+CPU_RESET_TYPE
+BistEnableDisable (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN CPU_STRAP_SET *CpuStrapSet,
+ IN PEI_CPU_PLATFORM_POLICY_PPI *CpuPlatformPolicyPpi
+ )
+{
+ if (CpuStrapSet->Bist == CpuPlatformPolicyPpi->CpuConfig->BistOnReset) {
+ return NO_RESET;
+ } else {
+ CpuStrapSet->Bist = CpuPlatformPolicyPpi->CpuConfig->BistOnReset;
+ DEBUG ((EFI_D_INFO, "BIST configuration doesn't match the setup value\n"));
+ return WARM_RESET;
+ }
+}
+
+/**
+ This fuction compare Setup Options of Processor Flex Multiplier against the CPU Strap
+ and in case of mismatch requests reset
+
+ @param[in] PeiServices - For printouts
+ @param[in] CpuStrapSet - Strap current setting
+ @param[in] CpuPlatformPolicyPpi - Platform Policy PPI
+
+ @retval CPU_RESET_TYPE
+ @retval CPU_ONLY_RESET - if reset is needed
+ @retval NO_RESET - otherwise
+**/
+CPU_RESET_TYPE
+ProgramProcessorFlexMultiplier (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN CPU_STRAP_SET *CpuStrapSet,
+ IN PEI_CPU_PLATFORM_POLICY_PPI *CpuPlatformPolicyPpi
+ )
+{
+ UINT64 FlexRatioData;
+ UINT64 CurrentClockFlexRatio;
+ UINT64 MsrData;
+ CPU_RESET_TYPE ResetType;
+
+ ResetType = NO_RESET;
+
+ ///
+ /// Perform Flex Ratio if enabled by user in Setup screen
+ ///
+ if (CpuPlatformPolicyPpi->CpuConfig->CpuRatioOverride) {
+ FlexRatioData = (UINT64) (CpuPlatformPolicyPpi->CpuConfig->CpuRatio);
+ } else {
+ ///
+ /// Flex Ratio was set to disable. Reset to Max Non-Turbo Ratio
+ ///
+ FlexRatioData = 0x0;
+ }
+ DEBUG ((EFI_D_INFO, "Setup Ratio is 0x%X\n", FlexRatioData));
+
+ ///
+ /// Read and save current Flex Ratio data; disregard enable bit (MSR 194h [15:8])
+ ///
+ MsrData = AsmReadMsr64 (MSR_FLEX_RATIO);
+ CurrentClockFlexRatio = ((RShiftU64 (MsrData, N_FLEX_RATIO)) & 0xFF);
+ DEBUG ((EFI_D_INFO, "Current Flex Ratio from MSR is 0x%X\n", CurrentClockFlexRatio));
+ DEBUG ((EFI_D_INFO, "Current Flex Ratio from CPU Strap: 0x%X\n", CpuStrapSet->FlexRatio));
+ ///
+ /// Check and set Flex Ratio to requested ratio if possible
+ ///
+ if (FlexRatioData == CpuStrapSet->FlexRatio) {
+ ///
+ /// Do nothing, ratio is already set to requested value and enabled
+ ///
+ DEBUG ((EFI_D_INFO, "No need to set Flex Ratio.\n"));
+ } else {
+ ///
+ /// Set Flex Ratio to user selected value
+ ///
+ /// Write new data to Flex Ratio register
+ /// First clear MSR of any previous value
+ ///
+ MsrData &= RATIO_FLEX_CLEAR_MASK;
+
+ ///
+ /// Enter the new data
+ ///
+ MsrData |= (LShiftU64 ((FlexRatioData & 0xFF), N_FLEX_RATIO));
+ MsrData |= B_FLEX_EN;
+ AsmWriteMsr64 (MSR_FLEX_RATIO, MsrData);
+
+ ///
+ /// Set Soft Reset Data for Flex Ratio
+ ///
+ CpuStrapSet->FlexRatio = (UINT32) FlexRatioData;
+
+ ///
+ /// Set RESET flag
+ ///
+ DEBUG ((EFI_D_INFO, "Setting Flex Ratio to 0x%X\n", CpuStrapSet->FlexRatio));
+ ResetType |= WARM_RESET;
+ }
+
+ return ResetType;
+}
+
+static EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList[] = {
+ {
+ EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
+ &gPchInitPpiGuid,
+ SetCpuStrap
+ },
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiMasterBootModePpiGuid,
+ BuildBistHob
+ }
+};
+
+/**
+ Check if VT is fused and disabled by Setup Option so reset is needed
+
+ @param[in] CpuPlatformPolicyPpi - Platform Policy PPI
+
+ @retval CPU_RESET_TYPE
+ @retval NO_RESET - If no reset is needed
+ @retval COLDRESET - otherwise
+**/
+CPU_RESET_TYPE
+CheckVmxIfNeedReset (
+ IN PEI_CPU_PLATFORM_POLICY_PPI *CpuPlatformPolicyPpi
+ )
+{
+ UINT64 MsrIa32FeatureControl;
+ BOOLEAN CurrentVmxState;
+ EFI_CPUID_REGISTER Cpuid01 = { 0, 0, 0, 0 };
+
+ AsmCpuid (CPUID_VERSION_INFO, &Cpuid01.RegEax, &Cpuid01.RegEbx, &Cpuid01.RegEcx, &Cpuid01.RegEdx);
+
+ ///
+ /// Check if VMX is supported
+ ///
+ if ((Cpuid01.RegEcx & B_CPUID_VERSION_INFO_ECX_VME) == 0) {
+ return NO_RESET;
+ }
+
+ MsrIa32FeatureControl = AsmReadMsr64 (MSR_IA32_FEATURE_CONTROL);
+
+ ///
+ /// If unlocked, no reset needed.
+ ///
+ if ((MsrIa32FeatureControl & B_MSR_IA32_FEATURE_CONTROL_LOCK) == 0) {
+ return NO_RESET;
+ }
+
+ CurrentVmxState = (BOOLEAN) ((MsrIa32FeatureControl & B_MSR_IA32_FEATURE_CONTROL_EVT) != 0);
+
+ ///
+ /// Need to reset only if locked and VMX state has to be changed.
+ ///
+ if ((CurrentVmxState == (CpuPlatformPolicyPpi->CpuConfig->VmxEnable)) == CPU_FEATURE_ENABLE) {
+ return NO_RESET;
+ }
+ ///
+ /// We need a power good reset to unlock MSR_IA32_FEATURE_CONTROL.
+ ///
+ return COLDRESET;
+}
+
+/**
+ Set CPU strap setting for feature change
+
+ @param[in] PeiServices - Indirect reference to the PEI Services Table.
+ @param[in] NotifyDescriptor - Address of the notification descriptor data structure. Type
+ EFI_PEI_NOTIFY_DESCRIPTOR is defined above.
+ @param[in] Ppi - Address of the PPI that was installed.
+
+ @retval EFI_SUCCESS - Function completed successfully
+**/
+EFI_STATUS
+EFIAPI
+SetCpuStrap (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ EFI_STATUS Status;
+ CPU_STRAP_SET CpuStrapSet = { 0 };
+ UINT16 CpuStrapSetData;
+ volatile CPU_RESET_TYPE ResetType;
+ PCH_INIT_PPI *PchInitPpi;
+ PEI_CPU_PLATFORM_POLICY_PPI *CpuPlatformPolicyPpi;
+ UINT8 Data;
+
+ ResetType = NO_RESET;
+ CpuStrapSetData = 0;
+ Data = 0;
+
+ Status = PeiServicesLocatePpi (
+ &gPeiCpuPlatformPolicyPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &CpuPlatformPolicyPpi
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Locate PchInit Ppi
+ ///
+ Status = PeiServicesLocatePpi (
+ &gPchInitPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &PchInitPpi
+ );
+ if (Status == EFI_SUCCESS) {
+ ///
+ /// Get Cpu Strap Set Data
+ ///
+ DEBUG ((EFI_D_INFO, "Set PCH CPU Straps \n"));
+ Status = PchInitPpi->CpuStrapSet (PeiServices, GetCpuStrapSetData, &CpuStrapSetData);
+ *((UINT16 *) (&CpuStrapSet)) = CpuStrapSetData;
+ DEBUG ((EFI_D_INFO, "Current CPU Strap Data = 0x%04X\n", CpuStrapSetData));
+
+ if (Status == EFI_SUCCESS) {
+ ResetType |= SetActiveCoresAndSmtEnableDisable (PeiServices, &CpuStrapSet, CpuPlatformPolicyPpi);
+ ResetType |= BistEnableDisable (PeiServices, &CpuStrapSet, CpuPlatformPolicyPpi);
+
+ ///
+ /// Perform Flex Ratio if processor is fused to perform Flex Ratio
+ ///
+ if ((AsmReadMsr64 (MSR_FLEX_RATIO) & B_FLEX_EN) == B_FLEX_EN) {
+ ResetType |= ProgramProcessorFlexMultiplier (PeiServices, &CpuStrapSet, CpuPlatformPolicyPpi);
+ }
+
+ if (ResetType != NO_RESET) {
+ CpuStrapSetData = *((UINT16 *) (&CpuStrapSet));
+ DEBUG ((EFI_D_INFO, "New CPU Strap Data = 0x%04X\n", CpuStrapSetData));
+ Status = PchInitPpi->CpuStrapSet (
+ PeiServices,
+ SetCpuStrapSetData,
+ &CpuStrapSetData
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "NO Reset\n"));
+ ResetType = NO_RESET;
+ }
+ }
+ }
+ }
+
+ ResetType |= CheckVmxIfNeedReset (CpuPlatformPolicyPpi);
+
+ if (ResetType != NO_RESET) {
+ ///
+ /// Perform Warm or Cold Reset
+ ///
+ DEBUG (
+ (EFI_D_INFO,
+ "Reset Required. Performing Cold/Warm Reset to read the new strap values - ResetType = %x\n",
+ ResetType)
+ );
+ PerformWarmORColdReset (PeiServices, ResetType);
+ }
+
+ Status = PchInitPpi->CpuStrapSet (
+ PeiServices,
+ LockCpuStrapSetData,
+ &CpuStrapSetData
+ );
+ DEBUG ((EFI_D_INFO, "No Reset Required\n"));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialize prefetcher settings
+
+ @param[in] MlcStreamerprefecterEnabled - Enable/Disable MLC streamer prefetcher
+ @param[in] MlcSpatialPrefetcherEnabled - Enable/Disable MLC spatial prefetcher
+**/
+VOID
+ProcessorsPrefetcherInitialization (
+ IN UINTN MlcStreamerprefecterEnabled,
+ IN UINTN MlcSpatialPrefetcherEnabled
+ )
+{
+ UINT64 MsrValue;
+ MsrValue = AsmReadMsr64 (MISC_FEATURE_CONTROL);
+
+ if (MlcStreamerprefecterEnabled == CPU_FEATURE_DISABLE) {
+ MsrValue |= B_MISC_FEATURE_CONTROL_MLC_STRP;
+ }
+
+ if (MlcSpatialPrefetcherEnabled == CPU_FEATURE_DISABLE) {
+ MsrValue |= B_MISC_FEATURE_CONTROL_MLC_SPAP;
+ }
+
+ if ((MsrValue & (B_MISC_FEATURE_CONTROL_MLC_STRP | B_MISC_FEATURE_CONTROL_MLC_SPAP)) != 0) {
+ AsmWriteMsr64 (MISC_FEATURE_CONTROL, MsrValue);
+ }
+
+ return;
+}
+
+/**
+ Based on ResetType, perform warm or cold reset using PCH Reset PPI
+
+ @param[in] PeiServices - Indirect reference to the PEI Services Table.
+ @param[in] ResetType - CPU_RESET_TYPE to indicate which reset shoudl be performed.
+
+ @exception EFI_UNSUPPORTED - Reset type unsupported
+ @retval EFI_SUCCESS - function successfully (system should already reset)
+**/
+EFI_STATUS
+PerformWarmORColdReset (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN CPU_RESET_TYPE ResetType
+ )
+{
+ PCH_RESET_PPI *PchResetPpi;
+ EFI_STATUS Status;
+
+ ///
+ /// Loccate Reset PPI
+ ///
+ Status = (*PeiServices)->LocatePpi (
+ PeiServices,
+ &gPchResetPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &PchResetPpi
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Perfrom the requested reset using PCH reset PPI
+ ///
+ Status = EFI_SUCCESS;
+ switch (ResetType) {
+ case WARM_RESET:
+ PchResetPpi->Reset (PchResetPpi, RESET_PPI_WARM_RESET);
+ break;
+
+ case COLDRESET:
+ PchResetPpi->Reset (PchResetPpi, RESET_PPI_COLD_RESET);
+ break;
+
+ default:
+ DEBUG ((EFI_D_ERROR, "CpuInitPeim: PerformWarmORColdReset - ResetType %d not supported: \n", ResetType));
+ Status = EFI_UNSUPPORTED;
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return Status;
+}
+
+/**
+ Initializes XE OR Overclocking support in the processor.
+
+ @param[in] PowerMgmtConfig Pointer to Policy protocol instance
+
+ @retval EFI_SUCCESS
+**/
+EFI_STATUS
+XeInit (
+ IN OUT POWER_MGMT_CONFIG_PPI *PowerMgmtConfig,
+ IN OUT OVERCLOCKING_CONFIG_PPI *OcConfig
+ )
+{
+ MSR_REGISTER TurboRatioLimit;
+ MSR_REGISTER FlexRatioMsr;
+ MSR_REGISTER TempMsr;
+ MSR_REGISTER RingRatioMsr;
+ UINT8 CoreCount;
+ UINT8 OverclockingBins;
+ UINT8 OneCoreRatioLimit;
+ UINT8 TwoCoreRatioLimit;
+ UINT8 ThreeCoreRatioLimit;
+ UINT8 FourCoreRatioLimit;
+ UINT8 RatioLimitProgrammble;
+ UINT16 MaxBusRatio;
+
+ if ((PowerMgmtConfig->Xe == 0)) {
+ ///
+ /// XE is disabled
+ ///
+ return EFI_SUCCESS;
+ }
+
+ TurboRatioLimit.Qword = AsmReadMsr64 (MSR_TURBO_RATIO_LIMIT);
+ OneCoreRatioLimit = (UINT8) (TurboRatioLimit.Dwords.Low & B_MSR_TURBO_RATIO_LIMIT_1C);
+ TwoCoreRatioLimit = (UINT8) RShiftU64 (
+ (TurboRatioLimit.Dwords.Low & B_MSR_TURBO_RATIO_LIMIT_2C),
+ N_MSR_TURBO_RATIO_LIMIT_2C
+ );
+ ThreeCoreRatioLimit = (UINT8) RShiftU64 (
+ (TurboRatioLimit.Dwords.Low & B_MSR_TURBO_RATIO_LIMIT_3C),
+ N_MSR_TURBO_RATIO_LIMIT_3C
+ );
+ FourCoreRatioLimit = (UINT8) RShiftU64 (
+ (TurboRatioLimit.Dwords.Low & B_MSR_TURBO_RATIO_LIMIT_4C),
+ N_MSR_TURBO_RATIO_LIMIT_4C
+ );
+
+ ///
+ /// Check if XE capable
+ ///
+ FlexRatioMsr.Qword = AsmReadMsr64 (MSR_FLEX_RATIO);
+
+ ///
+ /// Overclocking availablity
+ ///
+ OverclockingBins = (UINT8) RShiftU64 ((FlexRatioMsr.Dwords.Low & B_OVERCLOCKING_BINS), N_OVERCLOCKING_BINS);
+
+ ///
+ /// Check if Turbo Ratio Limit is programmable
+ /// Platform Info MSR (0xCE) [28]
+ ///
+ TempMsr.Qword = AsmReadMsr64 (MSR_PLATFORM_INFO);
+ RatioLimitProgrammble = (UINT8) RShiftU64 (
+ (TempMsr.Qword & B_PLATFORM_INFO_RATIO_LIMIT),
+ N_PLATFORM_INFO_RATIO_LIMIT
+ );
+ ///
+ /// Get Maximum Non-Turbo bus ratio (HFM) from Platform Info MSR Bits[15:8]
+ ///
+ MaxBusRatio = TempMsr.Bytes.SecondByte;
+
+ ///
+ /// Check if processor turbo-ratio can be overriden:
+ /// BWG Section 14.14.2
+ /// If PLATFORM INFO MSR [28] == 1 and FLEX_RATIO MSR [19:17] != 0
+ /// Processor with capability to override turbo-ratio detected (either XE or Overclocking part detected)
+ ///
+ if ((RatioLimitProgrammble == 0) || (OverclockingBins == 0)) {
+ ///
+ /// Neither XE nor Overclocking Capable processor.
+ ///
+ DEBUG ((EFI_D_WARN, "WARNING: Trying to configure XE params on a non-XE processor\n"));
+ return EFI_SUCCESS;
+ }
+ ///
+ /// For Overclocking parts, verify ratio overide is within the allowable limits
+ ///
+ if ((RatioLimitProgrammble) && (OverclockingBins < MAX_OVERCLOCKING_BINS)) {
+ if (PowerMgmtConfig->RatioLimit[0] > (OneCoreRatioLimit + OverclockingBins)) {
+ PowerMgmtConfig->RatioLimit[0] = OneCoreRatioLimit + OverclockingBins;
+ }
+
+ if (PowerMgmtConfig->RatioLimit[1] > (TwoCoreRatioLimit + OverclockingBins)) {
+ PowerMgmtConfig->RatioLimit[1] = TwoCoreRatioLimit + OverclockingBins;
+ }
+
+ if (PowerMgmtConfig->RatioLimit[2] > (ThreeCoreRatioLimit + OverclockingBins)) {
+ PowerMgmtConfig->RatioLimit[2] = ThreeCoreRatioLimit + OverclockingBins;
+ }
+
+ if (PowerMgmtConfig->RatioLimit[3] > (FourCoreRatioLimit + OverclockingBins)) {
+ PowerMgmtConfig->RatioLimit[3] = FourCoreRatioLimit + OverclockingBins;
+ }
+ }
+
+ if ((RatioLimitProgrammble)) {
+ ///
+ /// Now initialize turbo ratio limit MSR
+ /// Find the number of active cores and initialize the ratio limits only if they are available.
+ /// Also program the VID value for the new max Turbo ratio by programming Flex Ratio MSR.
+ ///
+ TempMsr.Qword = AsmReadMsr64 (MSR_CORE_THREAD_COUNT);
+ CoreCount = (UINT8) RShiftU64 (TempMsr.Dwords.Low, N_CORE_COUNT_OFFSET);
+
+ if (PowerMgmtConfig->RatioLimit[0] >= PowerMgmtConfig->RatioLimit[1] &&
+ PowerMgmtConfig->RatioLimit[0] >= PowerMgmtConfig->RatioLimit[2] &&
+ PowerMgmtConfig->RatioLimit[0] >= PowerMgmtConfig->RatioLimit[3] &&
+ PowerMgmtConfig->RatioLimit[1] >= MaxBusRatio &&
+ PowerMgmtConfig->RatioLimit[2] >= MaxBusRatio &&
+ PowerMgmtConfig->RatioLimit[3] >= MaxBusRatio
+ ) {
+ if (CoreCount >= 1) {
+ TurboRatioLimit.Dwords.Low &= ~B_MSR_TURBO_RATIO_LIMIT_1C;
+ TurboRatioLimit.Dwords.Low |= PowerMgmtConfig->RatioLimit[0];
+ }
+
+ if (CoreCount >= 2) {
+ TurboRatioLimit.Dwords.Low &= ~B_MSR_TURBO_RATIO_LIMIT_2C;
+ TurboRatioLimit.Dwords.Low |= LShiftU64 (PowerMgmtConfig->RatioLimit[1], 8);
+ }
+
+ if (CoreCount >= 3) {
+ TurboRatioLimit.Dwords.Low &= ~B_MSR_TURBO_RATIO_LIMIT_3C;
+ TurboRatioLimit.Dwords.Low |= LShiftU64 (PowerMgmtConfig->RatioLimit[2], 16);
+ }
+
+ if (CoreCount >= 4) {
+ TurboRatioLimit.Dwords.Low &= ~B_MSR_TURBO_RATIO_LIMIT_4C;
+ TurboRatioLimit.Dwords.Low |= LShiftU64 (PowerMgmtConfig->RatioLimit[3], 24);
+ }
+
+ AsmWriteMsr64 (MSR_TURBO_RATIO_LIMIT, TurboRatioLimit.Qword);
+ }
+ }
+
+ ///
+ /// For Overclocking parts, if a non-default ring ratio is specificed, we need to
+ /// update the ring ratio limit MSR's max limit
+ ///
+ if ((OverclockingBins != 0) && (OcConfig->ClrMaxOcTurboRatio != 0)) {
+ RingRatioMsr.Qword = AsmReadMsr64 (MSR_RING_RATIO_LIMIT);
+ RingRatioMsr.Bytes.FirstByte &= ~MSR_MAX_RING_RATIO_LIMIT_MASK;
+ RingRatioMsr.Bytes.FirstByte |= OcConfig->ClrMaxOcTurboRatio & MSR_MAX_RING_RATIO_LIMIT_MASK;
+ AsmWriteMsr64 (MSR_RING_RATIO_LIMIT, RingRatioMsr.Qword);
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialize performance and power management features
+
+ @param[in] CpuPlatformPolicyPpi - The CPU Platform Policy PPI instance
+**/
+VOID
+ProcessorsPerfPowerInit (
+ IN OUT PEI_CPU_PLATFORM_POLICY_PPI *CpuPlatformPolicyPpi
+ )
+{
+ EFI_CPUID_REGISTER Cpuid = { 0, 0, 0, 0 };
+ MSR_REGISTER TempMsr;
+ UINT8 TccActivationOffsetProgrammable;
+ UINT16 MaxBusRatio;
+ UINT16 MinBusRatio;
+ UINT32 Remainder;
+ POWER_MGMT_CONFIG_PPI *PowerMgmtConfig;
+ MSR_REGISTER TurboRatioLimit;
+ UINT8 OneCoreRatioLimit;
+ MSR_REGISTER Ia32MiscEnable;
+ CPU_FAMILY CpuFamilyId;
+ CPU_STEPPING CpuStepping;
+ UINT8 TccActivationOffsetMask;
+ UINT32 WriteFivrSpreadCmd;
+ UINT32 ReadFivrSpreadCmd;
+ UINT32 ReadFivrSpreadData;
+ UINT32 WriteFivrSpreadData;
+ UINT32 MailboxStatus;
+
+ PowerMgmtConfig = CpuPlatformPolicyPpi->PowerMgmtConfig;
+ CpuFamilyId = GetCpuFamily();
+ CpuStepping = GetCpuStepping();
+
+ ///
+ /// Initializes Processor Prefetcher
+ ///
+ ProcessorsPrefetcherInitialization (
+ CpuPlatformPolicyPpi->CpuConfig->MlcStreamerPrefetcher,
+ CpuPlatformPolicyPpi->CpuConfig->MlcSpatialPrefetcher
+ );
+
+ TempMsr.Qword = AsmReadMsr64 (MSR_PLATFORM_INFO);
+
+ ///
+ /// Get Tcc Activation Offset Programmable Setting from Platform Info MSR Bits[30]
+ ///
+ TccActivationOffsetProgrammable = (UINT8) RShiftU64 (
+ (TempMsr.Qword & B_PLATFORM_INFO_PROG_TCC_ACTIVATION_OFFSET),
+ N_PLATFORM_INFO_PROG_TCC_ACTIVATION_OFFSET
+ );
+ ///
+ /// Get Maximum Non-Turbo bus ratio (HFM) from Platform Info MSR Bits[15:8]
+ ///
+ MaxBusRatio = TempMsr.Bytes.SecondByte;
+ ///
+ /// Get Maximum Efficiency bus ratio (LFM) from Platform Info MSR Bits[47:40]
+ ///
+ MinBusRatio = TempMsr.Bytes.SixthByte;
+ ///
+ /// Tcc activation offset in temperature target MSR changes from 4 bits [27:24] to 6 bits [29:24] on ULT C step onwards
+ ///
+ if ((CpuFamilyId == EnumCpuHswUlt) && (CpuStepping >= EnumHswUltC0)) {
+ TccActivationOffsetMask = 0x3F;
+ } else {
+ TccActivationOffsetMask = 0xF;
+ }
+ ///
+ /// If User slects TccActivationOffset greater than supported progam max supported.
+ ///
+ if(PowerMgmtConfig->TccActivationOffset > TccActivationOffsetMask){
+ PowerMgmtConfig->TccActivationOffset = TccActivationOffsetMask;
+ }
+ ///
+ /// First check if TCC Activation Offset is programmable PLATFORM INFO MSR [30]
+ /// If TCC Activation Offset is programable, program the TCC Activation offset value
+ /// from Policy, and the Tcc activation offset programming should be dependency on RESET_CPL done.
+ ///
+ if (TccActivationOffsetProgrammable) {
+ TempMsr.Qword = AsmReadMsr64 (MSR_TEMPERATURE_TARGET);
+ TempMsr.Dwords.Low &= ~(TccActivationOffsetMask << N_MSR_TEMPERATURE_TARGET_TCC_OFFSET_LIMIT);
+ PowerMgmtConfig->TccActivationOffset &= TccActivationOffsetMask;
+ TempMsr.Dwords.Low |= LShiftU64 (PowerMgmtConfig->TccActivationOffset, N_MSR_TEMPERATURE_TARGET_TCC_OFFSET_LIMIT);
+ AsmWriteMsr64 (MSR_TEMPERATURE_TARGET, TempMsr.Qword);
+ }
+ ///
+ /// Program Voltage regulator Current Limit's
+ ///
+ TempMsr.Qword = AsmReadMsr64 (MSR_VR_CURRENT_CONFIG);
+ TempMsr.Dwords.High &= ~PSIX_THRESHOLD_MASK;
+ if (CpuPlatformPolicyPpi->Revision >= PEI_CPU_PLATFORM_POLICY_PPI_REVISION_5) {
+ TempMsr.Dwords.High |= ((PowerMgmtConfig->Psi3Threshold << 20) | (PowerMgmtConfig->Psi2Threshold << 10) | PowerMgmtConfig->Psi1Threshold );
+ if ((CpuFamilyId == EnumCpuHswUlt) && (PowerMgmtConfig->VrPSI4enable)) {
+ TempMsr.Dwords.High |= (0x1 << 30);
+ }
+ }
+ if (PowerMgmtConfig->VrCurrentLimit != 0) {
+ ///
+ /// Check the VR_CURRENT_LOCK bit
+ ///
+ if ((TempMsr.Dwords.Low & B_CURRENT_LIMIT_LOCK) == 0) {
+ TempMsr.Dwords.Low &= ~B_CURRENT_LIMIT_MASK;
+ TempMsr.Dwords.Low |= PowerMgmtConfig->VrCurrentLimit;
+ } else {
+ DEBUG ((EFI_D_INFO, "PPM:: VR Current Limit in MSR_VR_CURRENT_CONFIG is locked\n"));
+ }
+ }
+ ///
+ /// Set CURRENT_LIMIT_LOCK bit in VR_Config_MSR
+ ///
+ if (PowerMgmtConfig->VrCurrentLimitLock) {
+ TempMsr.Dwords.Low |= B_CURRENT_LIMIT_LOCK;
+ }
+
+ AsmWriteMsr64 (MSR_VR_CURRENT_CONFIG, TempMsr.Qword);
+
+ if (CpuPlatformPolicyPpi->Revision >= PEI_CPU_PLATFORM_POLICY_PPI_REVISION_4) {
+ TempMsr.Qword = AsmReadMsr64 (MSR_VR_MISC_CONFIG);
+ TempMsr.Dwords.High = RRotU32 (TempMsr.Dwords.High, 8);
+ if (PowerMgmtConfig->VrMiscIoutSlope <= 1023) {
+ ///
+ /// Update IOUT_SLOPE [49:40]
+ /// Must be 0 to 0x3FF (1023 decimal)
+ ///
+ TempMsr.Dwords.High &= ~0x3FF;
+ TempMsr.Dwords.High |= PowerMgmtConfig->VrMiscIoutSlope;
+ }
+ TempMsr.Dwords.High = LRotU32 (TempMsr.Dwords.High, 8);
+ if ((PowerMgmtConfig->VrMiscIoutOffset != 0) && (PowerMgmtConfig->VrMiscIoutOffset <= 625)) {
+ ///
+ /// Update IOUT_OFFSET[39:32]
+ /// MSR encoding = int(value*2^8+0.0625) for positive offsets
+ /// inv(int(value*2^8+0.0625))+1 for negative offsets
+ /// +0.0625 could be ignored
+ ///
+ PowerMgmtConfig->VrMiscIoutOffset = (UINT16) DivU64x32Remainder (
+ (UINT64) MultU64x32 (PowerMgmtConfig->VrMiscIoutOffset, (UINT32) LShiftU64 (1, 8)),
+ 10000,
+ &Remainder
+ );
+ if (Remainder >= 5000) {
+ PowerMgmtConfig->VrMiscIoutOffset += 1;
+ }
+ if (PowerMgmtConfig->VrMiscIoutOffsetSign == 1) {
+ ///
+ /// This is negative offset
+ ///
+ PowerMgmtConfig->VrMiscIoutOffset = (UINT8) (~PowerMgmtConfig->VrMiscIoutOffset + 1);
+ }
+ TempMsr.Dwords.High &= ~0xFF;
+ TempMsr.Dwords.High |= PowerMgmtConfig->VrMiscIoutOffset;
+ }
+ AsmWriteMsr64 (MSR_VR_MISC_CONFIG, TempMsr.Qword);
+ }
+
+ if (CpuPlatformPolicyPpi->Revision >= PEI_CPU_PLATFORM_POLICY_PPI_REVISION_3) {
+ TempMsr.Qword = AsmReadMsr64 (MSR_VR_MISC_CONFIG);
+ TempMsr.Dwords.Low = RRotU32 (TempMsr.Dwords.Low, N_MSR_VR_MISC_CONFIG_MIN_VID_OFFSET);
+ ///
+ /// Update MIN_VID [31:24]
+ /// Must be 0 to 0xFF (255 decimal) resolution 10mV
+ /// 0 equal to 0mV; 0xFF (255 decimal) equal to 2550mV
+ ///
+ TempMsr.Dwords.Low &= ~B_MSR_VR_MISC_CONFIG_MIN_VID_MASK;
+ TempMsr.Dwords.Low |= PowerMgmtConfig->VrMiscMinVid;
+ TempMsr.Dwords.Low = LRotU32 (TempMsr.Dwords.Low, N_MSR_VR_MISC_CONFIG_MIN_VID_OFFSET);
+
+ ///
+ /// Update IDLE_EXIT_RAMP_RATE[50]
+ ///
+ TempMsr.Qword &= ~B_MSR_VR_MISC_CONFIG_IDLE_EXIT_RAMP_RATE;
+ if (PowerMgmtConfig->VrMiscIdleExitRampRate) {
+ TempMsr.Qword |= B_MSR_VR_MISC_CONFIG_IDLE_EXIT_RAMP_RATE;
+ }
+
+ ///
+ /// Update IDLE_ENTRY_RAMP_RATE[51]
+ ///
+ TempMsr.Qword &= ~B_MSR_VR_MISC_CONFIG_IDLE_ENTRY_RAMP_RATE;
+ if (PowerMgmtConfig->VrMiscIdleEntryRampRate) {
+ TempMsr.Qword |= B_MSR_VR_MISC_CONFIG_IDLE_ENTRY_RAMP_RATE;
+ }
+
+ ///
+ /// Update IDLE_ENTRY_DECAY_ENABLE[52]
+ ///
+ TempMsr.Qword &= ~B_MSR_VR_MISC_CONFIG_IDLE_ENTRY_DECAY_ENABLE;
+ if (PowerMgmtConfig->VrMiscIdleEntryDecayEnable) {
+ TempMsr.Qword |= B_MSR_VR_MISC_CONFIG_IDLE_ENTRY_DECAY_ENABLE;
+ }
+
+ if (CpuFamilyId == EnumCpuHswUlt) {
+ ///
+ /// Update IDLE_ENTRY_DECAY_ENABLE[52]
+ ///
+ TempMsr.Qword &= ~B_MSR_VR_MISC_CONFIG_SLOW_SLEW_RATE_CONFIG_MASK;
+ switch (PowerMgmtConfig->VrMiscSlowSlewRateConfig) {
+ case 1:
+ TempMsr.Qword |= V_MSR_VR_MISC_CONFIG_SLOW_SLEW_RATE_CONFIG_FAST_4;
+ break;
+ case 2:
+ TempMsr.Qword |= V_MSR_VR_MISC_CONFIG_SLOW_SLEW_RATE_CONFIG_FAST_8;
+ break;
+ case 3:
+ TempMsr.Qword |= V_MSR_VR_MISC_CONFIG_SLOW_SLEW_RATE_CONFIG_FAST_16;
+ break;
+ case 0:
+ default:
+ TempMsr.Qword |= V_MSR_VR_MISC_CONFIG_SLOW_SLEW_RATE_CONFIG_FAST_2;
+ break;
+ }
+ }
+ AsmWriteMsr64 (MSR_VR_MISC_CONFIG, TempMsr.Qword);
+
+ if (CpuFamilyId == EnumCpuHswUlt) {
+ TempMsr.Qword = AsmReadMsr64 (MSR_VR_MISC_CONFIG2);
+ ///
+ /// Update FAST_RAMP_VOLTAGE [7:0]
+ /// Must be 0 to 0xFF (255 decimal) resolution 10mV
+ /// 0 equal to 0mV; 0xFF (255 decimal) equal to 2550mV
+ ///
+ TempMsr.Bytes.FirstByte &= ~B_MSR_VR_MISC_CONFIG2_FAST_RAMP_VOLTAGE_MASK;
+ TempMsr.Bytes.FirstByte |= PowerMgmtConfig->VrMisc2FastRampVoltage;
+
+ ///
+ /// Update MIN_C8_VOLTAGE [15:8]
+ /// Must be 0 to 0xFF (255 decimal) resolution 10mV
+ /// 0 equal to 0mV; 0xFF (255 decimal) equal to 2550mV
+ ///
+ TempMsr.Bytes.SecondByte &= ~B_MSR_VR_MISC_CONFIG2_MIN_C8_VOLTAGE_MASK;
+ TempMsr.Bytes.SecondByte |= PowerMgmtConfig->VrMisc2MinC8Voltage;
+
+ AsmWriteMsr64 (MSR_VR_MISC_CONFIG2, TempMsr.Qword);
+ }
+ }
+ ///
+ /// Initializes XE OR Overclocking support
+ ///
+ XeInit (CpuPlatformPolicyPpi->PowerMgmtConfig, CpuPlatformPolicyPpi->OverclockingConfig);
+
+ ///
+ /// Set processor P state to HFM, LFM or TURBO
+ ///
+ AsmCpuid (CPUID_VERSION_INFO, &Cpuid.RegEax, &Cpuid.RegEbx, &Cpuid.RegEcx, &Cpuid.RegEdx);
+ ///
+ /// Check to see if CPU is GV3 capable - GV3 is fused Enabled
+ ///
+ if ((Cpuid.RegEcx & B_CPUID_VERSION_INFO_ECX_EIST) == B_CPUID_VERSION_INFO_ECX_EIST) {
+ Ia32MiscEnable.Qword = AsmReadMsr64 (MSR_IA32_MISC_ENABLE);
+ Ia32MiscEnable.Qword |= B_MSR_IA32_MISC_ENABLE_EIST;
+ AsmWriteMsr64 (MSR_IA32_MISC_ENABLE, Ia32MiscEnable.Qword);
+
+ TempMsr.Qword = AsmReadMsr64 (MSR_IA32_PERF_CTRL);
+ TempMsr.Qword &= ~B_IA32_PERF_CTRLP_STATE_TARGET;
+
+ if ((CpuPlatformPolicyPpi->Revision >= PEI_CPU_PLATFORM_POLICY_PPI_REVISION_3) && (PowerMgmtConfig->BootInLfm == 2)) {
+ ///
+ /// Set processor P state as TURBO_RATIO_LIMIT_1C if available
+ ///
+ AsmCpuid (CPUID_POWER_MANAGEMENT_PARAMS, &Cpuid.RegEax, &Cpuid.RegEbx, &Cpuid.RegEcx, &Cpuid.RegEdx);
+ if (((Cpuid.RegEax & B_CPUID_POWER_MANAGEMENT_EAX_TURBO) == B_CPUID_POWER_MANAGEMENT_EAX_TURBO) ||
+ ((Ia32MiscEnable.Qword & B_MSR_IA32_MISC_DISABLE_TURBO) == B_MSR_IA32_MISC_DISABLE_TURBO)) {
+ ///
+ /// Temporarily enable Turbo and it will be reset in DXE phase
+ ///
+ Ia32MiscEnable.Qword &= ~B_MSR_IA32_MISC_DISABLE_TURBO;
+ AsmWriteMsr64 (MSR_IA32_MISC_ENABLE, Ia32MiscEnable.Qword);
+ ///
+ /// Set processor P state as TURBO_RATIO_LIMIT_1C
+ ///
+ TurboRatioLimit.Qword = AsmReadMsr64 (MSR_TURBO_RATIO_LIMIT);
+ OneCoreRatioLimit = (UINT8) (TurboRatioLimit.Dwords.Low & B_MSR_TURBO_RATIO_LIMIT_1C);
+ TempMsr.Qword |= LShiftU64 (OneCoreRatioLimit, N_IA32_PERF_CTRLP_STATE_TARGET);
+ } else {
+ ///
+ /// Turbo is not available, down to HFM
+ ///
+ DEBUG ((EFI_D_INFO, "CPU: Turbo mode is not available, down to HFM mode.\n"));
+ TempMsr.Qword |= LShiftU64 (MaxBusRatio, N_IA32_PERF_CTRLP_STATE_TARGET);
+ }
+ } else if (PowerMgmtConfig->BootInLfm == CPU_FEATURE_DISABLE) {
+ ///
+ /// Set processor P state as HFM
+ ///
+ TempMsr.Qword |= LShiftU64 (MaxBusRatio, N_IA32_PERF_CTRLP_STATE_TARGET);
+ } else {
+ ///
+ /// Set processor P state as LFM
+ ///
+ TempMsr.Qword |= LShiftU64 (MinBusRatio, N_IA32_PERF_CTRLP_STATE_TARGET);
+ }
+
+ AsmWriteMsr64 (MSR_IA32_PERF_CTRL, TempMsr.Qword);
+ }
+
+ ///
+ /// FIVR Spread Spectrum control is available on C0 steppings onward for all CPU families
+ ///
+ if ((CpuFamilyId == EnumCpuHswUlt && CpuStepping >= EnumHswUltC0) ||
+ (CpuFamilyId == EnumCpuHsw && CpuStepping >= EnumHswC0) ||
+ (CpuFamilyId == EnumCpuCrw && CpuStepping >= EnumCrwC0)){
+
+ ///
+ /// FivrSscPercent is specified in 1/10th percent increments. Range is 0-249.
+ ///
+ if (PowerMgmtConfig->FivrSscPercent > MAX_FIVR_SSC_PERCENT) {
+ PowerMgmtConfig->FivrSscPercent = MAX_FIVR_SSC_PERCENT;
+ }
+
+ ///
+ /// Read current FIVR SSC Spread percentage
+ ///
+ ReadFivrSpreadCmd = 0x8000000E;
+ ReadFivrSpreadData = 0;
+ MailboxRead(MAILBOX_TYPE_PCODE, ReadFivrSpreadCmd, &ReadFivrSpreadData, &MailboxStatus);
+
+//(AMI_CHG)>
+ {
+ UINT32 i = 0;
+ while (MailboxStatus == PCODE_MAILBOX_CC_VR_INTERFACE_LOCKED) {
+ MailboxRead(MAILBOX_TYPE_PCODE, ReadFivrSpreadCmd, &ReadFivrSpreadData, &MailboxStatus);
+ i++;
+ if (i == 100) break;
+ }
+ }
+//<(AMI_CHG)
+
+ if (PowerMgmtConfig->FivrSscEnable) {
+ WriteFivrSpreadData = ( ((PowerMgmtConfig->FivrSscPercent)*1024)/NUM_TENTHS_TO_PERCENTAGE) | FIVR_SSC_LOCK_BIT;
+ }
+ else {
+ ///
+ /// If disabling FIVR SSC, send 0% spread and lock interface
+ ///
+
+ WriteFivrSpreadData = FIVR_SSC_LOCK_BIT;
+ }
+
+ DEBUG ((EFI_D_INFO, "FIVR: Read FIVR Spread = %X, Write FIVR Spread = %X\n", ReadFivrSpreadData, WriteFivrSpreadData));
+ ///
+ /// Only update SSC percentage if needed
+ ///
+ if (ReadFivrSpreadData != WriteFivrSpreadData) {
+ DEBUG ((EFI_D_INFO, "FIVR: Update FIVR Spread = %X\n", WriteFivrSpreadData));
+
+ WriteFivrSpreadCmd = 0x8000000F;
+ MailboxWrite(MAILBOX_TYPE_PCODE, WriteFivrSpreadCmd, WriteFivrSpreadData, &MailboxStatus);
+
+//(AMI_CHG)>
+ {
+ UINT32 i = 0;
+ while (MailboxStatus == PCODE_MAILBOX_CC_VR_INTERFACE_LOCKED) {
+ MailboxWrite(MAILBOX_TYPE_PCODE, WriteFivrSpreadCmd, WriteFivrSpreadData, &MailboxStatus);
+ i++;
+ if (i == 100) break;
+ }
+ }
+//<(AMI_CHG)
+
+ if (MailboxStatus != PCODE_MAILBOX_CC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "FIVR: Error updating FIVR Spread. Mailbox Status = %X\n", MailboxStatus));
+ }
+ }
+ }
+ else {
+ DEBUG ((EFI_D_ERROR, "FIVR: FIVR Spread adjustment requires C0 stepping or greater. Bypassing FIVR Spread flow.\n"));
+ }
+
+ return;
+}
+
+/**
+ Loads the Processor Microcode & Install the Cache PPI
+
+ @param[in] FfsHeader - Pointer to an alleged FFS file.
+ @param[in] PeiServices - General purpose services available to every PEIM.
+
+ @retval EFI_STATUS - the status code returned from any sub-routine
+**/
+EFI_STATUS
+PeimInitializeCpu (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ PEI_CPU_PLATFORM_POLICY_PPI *CpuPlatformPolicyPpi;
+
+ Status = PeiServicesLocatePpi (
+ &gPeiCpuPlatformPolicyPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &CpuPlatformPolicyPpi
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+
+ }
+
+ //
+ // Dump Cpu Platform Policy
+ //
+ CpuPeiPolicyDump(CpuPlatformPolicyPpi);
+
+ ///
+ /// Install Cache PPI
+ ///
+ Status = CacheInitPpiInit ();
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Install Notify
+ ///
+ Status = PeiServicesNotifyPpi (&mNotifyList[0]);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Initializes Overclocking support
+ ///
+ CpuOcInit(PeiServices, CpuPlatformPolicyPpi);
+
+ ///
+ /// Initializes Performance and Power Settings
+ ///
+ ProcessorsPerfPowerInit (CpuPlatformPolicyPpi);
+
+ ///
+ /// Init XMM support
+ ///
+ XmmInit ();
+
+ ///
+ /// Pfat Initialization
+ ///
+ PfatInit (PeiServices, CpuPlatformPolicyPpi);
+
+ ///
+ /// Boot Guard Initializatoin
+ ///
+ BootGuardInit (PeiServices, CpuPlatformPolicyPpi);
+
+ return Status;
+}
+
+/**
+ Build BIST HOB
+
+ @param[in] PeiServices - Indirect reference to the PEI Services Table.
+ @param[in] NotifyDescriptor - Address of the notification descriptor data structure. Type
+ EFI_PEI_NOTIFY_DESCRIPTOR is defined above.
+ @param[in] Ppi - Address of the PPI that was installed.
+
+ @retval EFI_SUCCESS - Hob built or not necessary
+**/
+EFI_STATUS
+EFIAPI
+BuildBistHob (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ EFI_STATUS Status;
+ EFI_BOOT_MODE BootMode;
+ EFI_SEC_PLATFORM_INFORMATION_PPI *SecPlatformInformationPpi;
+ UINT64 InformationSize;
+ SEC_PLATFORM_INFORMATION_RECORD *SecPlatformInformation;
+ VOID *Hob;
+
+ Status = (**PeiServices).GetBootMode (PeiServices, &BootMode);
+ if (!EFI_ERROR (Status) && (BootMode == BOOT_ON_S3_RESUME)) {
+ return EFI_SUCCESS;
+ }
+
+ Status = PeiServicesLocatePpi (
+ &gEfiSecPlatformInformationPpiGuid, ///< GUID
+ 0, ///< INSTANCE
+ NULL, ///< EFI_PEI_PPI_DESCRIPTOR
+ (VOID ** ) &SecPlatformInformationPpi ///< PPI
+ );
+
+ if (Status == EFI_NOT_FOUND) {
+ return EFI_SUCCESS;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ InformationSize = 0;
+ SecPlatformInformation = NULL;
+ Status = SecPlatformInformationPpi->PlatformInformation (
+ PeiServices,
+ &InformationSize,
+ SecPlatformInformation
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ Status = PeiServicesAllocatePool (
+ (UINTN) InformationSize,
+ (VOID **) &SecPlatformInformation
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = SecPlatformInformationPpi->PlatformInformation (
+ PeiServices,
+ &InformationSize,
+ SecPlatformInformation
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Hob = BuildGuidDataHob (
+ &gEfiHtBistHobGuid,
+ SecPlatformInformation,
+ (UINTN) InformationSize
+ );
+ ASSERT (Hob != NULL);
+
+ return Status;
+}
+
+/**
+ Dump RC CPU and PPM platform policies
+
+ @param[in] CpuPlatformPolicyPpi - Address of the cpu platform policy ppi.
+**/
+VOID
+CpuPeiPolicyDump (
+ IN PEI_CPU_PLATFORM_POLICY_PPI *CpuPlatformPolicyPpi
+ )
+{
+#ifdef EFI_DEBUG
+ UINTN Index;
+ CPU_CONFIG_PPI *CpuConfig;
+ POWER_MGMT_CONFIG_PPI *PowerMgmtConfig;
+ SECURITY_CONFIG_PPI *SecurityConfig;
+ OVERCLOCKING_CONFIG_PPI *OverclockingConfig;
+
+ CpuConfig = CpuPlatformPolicyPpi->CpuConfig;
+ PowerMgmtConfig = CpuPlatformPolicyPpi->PowerMgmtConfig;
+ SecurityConfig = CpuPlatformPolicyPpi->SecurityConfig;
+ OverclockingConfig = CpuPlatformPolicyPpi->OverclockingConfig;
+
+ DEBUG ((EFI_D_INFO, "\n------------------------ CpuPlatformPolicyPpi Dump Begin -----------------\n"));
+ //
+ // CPU_CONFIG
+ //
+ DEBUG ((EFI_D_INFO, " CPU:: BistOnReset : 0x%X\n", CpuConfig->BistOnReset));
+ DEBUG ((EFI_D_INFO, " CPU:: HyperThreading : 0x%X\n", CpuConfig->HyperThreading));
+ DEBUG ((EFI_D_INFO, " CPU:: CpuRatioOverride : 0x%X\n", CpuConfig->CpuRatioOverride));
+ DEBUG ((EFI_D_INFO, " CPU:: VmxEnable : 0x%X\n", CpuConfig->VmxEnable));
+ DEBUG ((EFI_D_INFO, " CPU:: Pfat Feature: 0x%X\n", CpuConfig->Pfat));
+ DEBUG ((EFI_D_INFO, " CPU:: MlcStreamerPrefetcher : 0x%X\n", CpuConfig->MlcStreamerPrefetcher));
+ DEBUG ((EFI_D_INFO, " CPU:: MlcSpatialPrefetcher : 0x%X\n", CpuConfig->MlcSpatialPrefetcher));
+ DEBUG ((EFI_D_INFO, " CPU:: ActiveCoreCount : 0x%X\n", CpuConfig->ActiveCoreCount));
+ DEBUG ((EFI_D_INFO, " CPU:: CpuRatio : 0x%X\n", CpuConfig->CpuRatio));
+ DEBUG ((EFI_D_INFO, " CPU:: MaxNonTurboRatio : 0x%X\n", CpuConfig->CpuMaxNonTurboRatio));
+ //
+ // POWER_MGMT_CONFIG
+ //
+ DEBUG ((EFI_D_INFO, " PPM:: BootInLfm : 0x%X\n", PowerMgmtConfig->BootInLfm));
+ DEBUG ((EFI_D_INFO, " PPM:: TccActivationOffset : 0x%X\n", PowerMgmtConfig->TccActivationOffset));
+ DEBUG ((EFI_D_INFO, " PPM:: VrCurrentLimit : 0x%X\n", PowerMgmtConfig->VrCurrentLimit));
+ DEBUG ((EFI_D_INFO, " PPM:: VrCurrentLimitLock : 0x%X\n", PowerMgmtConfig->VrCurrentLimitLock));
+ DEBUG ((EFI_D_INFO, " PPM:: Xe : 0x%X\n", PowerMgmtConfig->Xe));
+ DEBUG ((EFI_D_INFO, " PPM:: RatioLimit[4] : 0x%X , 0x%X , 0x%X , 0x%X \n", PowerMgmtConfig->RatioLimit[0], \
+ PowerMgmtConfig->RatioLimit[1], \
+ PowerMgmtConfig->RatioLimit[2], \
+ PowerMgmtConfig->RatioLimit[3]));
+ DEBUG ((EFI_D_INFO, " PPM:: VrMiscIoutSlope : 0x%X\n", PowerMgmtConfig->VrMiscIoutSlope));
+ DEBUG ((EFI_D_INFO, " PPM:: VrMiscIoutOffsetSign : 0x%X\n", PowerMgmtConfig->VrMiscIoutOffsetSign));
+ DEBUG ((EFI_D_INFO, " PPM:: VrMiscIoutOffset : 0x%X\n", PowerMgmtConfig->VrMiscIoutOffset));
+ DEBUG ((EFI_D_INFO, " PPM:: VrMiscMinVid : 0x%X\n", PowerMgmtConfig->VrMiscMinVid));
+ DEBUG ((EFI_D_INFO, " PPM:: VrMiscIdleExitRampRate : 0x%X\n", PowerMgmtConfig->VrMiscIdleExitRampRate));
+ DEBUG ((EFI_D_INFO, " PPM:: VrMiscIdleEntryRampRate : 0x%X\n", PowerMgmtConfig->VrMiscIdleEntryRampRate));
+ DEBUG ((EFI_D_INFO, " PPM:: VrMiscIdleEntryDecayEnable : 0x%X\n", PowerMgmtConfig->VrMiscIdleEntryDecayEnable));
+ DEBUG ((EFI_D_INFO, " PPM:: VrMiscSlowSlewRateConfig : 0x%X\n", PowerMgmtConfig->VrMiscSlowSlewRateConfig));
+ DEBUG ((EFI_D_INFO, " PPM:: VrMisc2FastRampVoltage : 0x%X\n", PowerMgmtConfig->VrMisc2FastRampVoltage));
+ DEBUG ((EFI_D_INFO, " PPM:: VrMisc2MinC8Voltage : 0x%X\n", PowerMgmtConfig->VrMisc2MinC8Voltage));
+ DEBUG ((EFI_D_INFO, " PPM:: FivrSscEnable : 0x%X\n", PowerMgmtConfig->FivrSscEnable));
+ DEBUG ((EFI_D_INFO, " PPM:: FivrSscPercent : 0x%X\n", PowerMgmtConfig->FivrSscPercent));
+
+ //
+ // SECURITY_CONFIG : PFAT_CONFIG
+ //
+ DEBUG ((EFI_D_INFO, " PFAT:: PUP_HEADER : Version : 0x%X\n", SecurityConfig->PfatConfig->PupHeader.Version));
+ DEBUG ((EFI_D_INFO, " PFAT:: PUP_HEADER : PlatId[16] :\n"));
+ for (Index = 0; Index < 16; Index++) {
+ if (Index == 15) {
+ DEBUG ((EFI_D_INFO, " 0x%X\n", SecurityConfig->PfatConfig->Ppdt.PlatId[Index]));
+ } else {
+ DEBUG ((EFI_D_INFO, " 0x%X ,", SecurityConfig->PfatConfig->Ppdt.PlatId[Index]));
+ }
+ }
+ DEBUG ((EFI_D_INFO, " \n"));
+ DEBUG ((EFI_D_INFO, " PFAT:: PUP_HEADER : PkgAttributes : 0x%X\n", SecurityConfig->PfatConfig->PupHeader.PkgAttributes));
+ DEBUG ((EFI_D_INFO, " PFAT:: PUP_HEADER : PslMajorVer : 0x%X\n", SecurityConfig->PfatConfig->PupHeader.PslMajorVer));
+ DEBUG ((EFI_D_INFO, " PFAT:: PUP_HEADER : PslMinorVer : 0x%X\n", SecurityConfig->PfatConfig->PupHeader.PslMinorVer));
+ DEBUG ((EFI_D_INFO, " PFAT:: PUP_HEADER : ScriptSectionSize : 0x%X\n", SecurityConfig->PfatConfig->PupHeader.ScriptSectionSize));
+ DEBUG ((EFI_D_INFO, " PFAT:: PUP_HEADER : DataSectionSize : 0x%X\n", SecurityConfig->PfatConfig->PupHeader.DataSectionSize));
+ DEBUG ((EFI_D_INFO, " PFAT:: PUP_HEADER : BiosSvn : 0x%X\n", SecurityConfig->PfatConfig->PupHeader.BiosSvn));
+ DEBUG ((EFI_D_INFO, " PFAT:: PUP_HEADER : EcSvn : 0x%X\n", SecurityConfig->PfatConfig->PupHeader.EcSvn));
+ DEBUG ((EFI_D_INFO, " PFAT:: PUP_HEADER : VendorSpecific : 0x%X\n", SecurityConfig->PfatConfig->PupHeader.VendorSpecific));
+ DEBUG ((EFI_D_INFO, " PFAT:: PPDT : PpdtSize : 0x%X\n", SecurityConfig->PfatConfig->Ppdt.PpdtSize));
+ DEBUG ((EFI_D_INFO, " PFAT:: PPDT : PpdtMajVer : 0x%X\n", SecurityConfig->PfatConfig->Ppdt.PpdtMajVer));
+ DEBUG ((EFI_D_INFO, " PFAT:: PPDT : PpdtMinVer : 0x%X\n", SecurityConfig->PfatConfig->Ppdt.PpdtMinVer));
+ DEBUG ((EFI_D_INFO, " PFAT:: PPDT : PlatId[16] :\n"));
+ for (Index = 0; Index < 16; Index++) {
+ if (Index == 15) {
+ DEBUG ((EFI_D_INFO, " 0x%X\n", SecurityConfig->PfatConfig->Ppdt.PlatId[Index]));
+ } else {
+ DEBUG ((EFI_D_INFO, " 0x%X ,", SecurityConfig->PfatConfig->Ppdt.PlatId[Index]));
+ }
+ }
+ DEBUG ((EFI_D_INFO, " \n"));
+ DEBUG ((EFI_D_INFO, " PFAT:: PPDT : PkeySlot0[32] :\n"));
+ for (Index = 0; Index < 32; Index++) {
+ if ((Index == 15) || (Index == 31)) {
+ DEBUG ((EFI_D_INFO, " 0x%X\n", SecurityConfig->PfatConfig->Ppdt.PkeySlot0[Index]));
+ } else {
+ DEBUG ((EFI_D_INFO, " 0x%X ,", SecurityConfig->PfatConfig->Ppdt.PkeySlot0[Index]));
+ }
+ }
+ DEBUG ((EFI_D_INFO, " \n"));
+ DEBUG ((EFI_D_INFO, " PFAT:: PPDT : PkeySlot1[32] :\n"));
+ for (Index = 0; Index < 32; Index++) {
+ if ((Index == 15) || (Index == 31)) {
+ DEBUG ((EFI_D_INFO, " 0x%X\n", SecurityConfig->PfatConfig->Ppdt.PkeySlot1[Index]));
+ } else {
+ DEBUG ((EFI_D_INFO, " 0x%X ,", SecurityConfig->PfatConfig->Ppdt.PkeySlot1[Index]));
+ }
+ }
+ DEBUG ((EFI_D_INFO, " \n"));
+ DEBUG ((EFI_D_INFO, " PFAT:: PPDT : PkeySlot2[32] :\n"));
+ for (Index = 0; Index < 32; Index++) {
+ if ((Index == 15)|| (Index == 31)) {
+ DEBUG ((EFI_D_INFO, " 0x%X\n", SecurityConfig->PfatConfig->Ppdt.PkeySlot2[Index]));
+ } else {
+ DEBUG ((EFI_D_INFO, " 0x%X ,", SecurityConfig->PfatConfig->Ppdt.PkeySlot2[Index]));
+ }
+ }
+ DEBUG ((EFI_D_INFO, " \n"));
+ DEBUG ((EFI_D_INFO, " PFAT:: PPDT : PfatModSvn : 0x%X\n", SecurityConfig->PfatConfig->Ppdt.PfatModSvn));
+ DEBUG ((EFI_D_INFO, " PFAT:: PPDT : BiosSvn : 0x%X\n", SecurityConfig->PfatConfig->Ppdt.BiosSvn));
+ DEBUG ((EFI_D_INFO, " PFAT:: PPDT : ExecLim : 0x%X\n", SecurityConfig->PfatConfig->Ppdt.ExecLim));
+ DEBUG ((EFI_D_INFO, " PFAT:: PPDT : PlatAttr : 0x%X\n", SecurityConfig->PfatConfig->Ppdt.PlatAttr));
+ DEBUG ((EFI_D_INFO, " PFAT:: PPDT : EcCmd : 0x%X\n", SecurityConfig->PfatConfig->Ppdt.EcCmd));
+ DEBUG ((EFI_D_INFO, " PFAT:: PPDT : EcData : 0x%X\n", SecurityConfig->PfatConfig->Ppdt.EcData));
+ DEBUG ((EFI_D_INFO, " PFAT:: PPDT : EcCmdGetSvn : 0x%X\n", SecurityConfig->PfatConfig->Ppdt.EcCmdGetSvn));
+ DEBUG ((EFI_D_INFO, " PFAT:: PPDT : EcCmdOpen : 0x%X\n", SecurityConfig->PfatConfig->Ppdt.EcCmdOpen));
+ DEBUG ((EFI_D_INFO, " PFAT:: PPDT : EcCmdClose : 0x%X\n", SecurityConfig->PfatConfig->Ppdt.EcCmdClose));
+ DEBUG ((EFI_D_INFO, " PFAT:: PPDT : EcCmdPortTest : 0x%X\n", SecurityConfig->PfatConfig->Ppdt.EcCmdPortTest));
+ DEBUG ((EFI_D_INFO, " PFAT:: PPDT : LastSfam : 0x%X\n", SecurityConfig->PfatConfig->Ppdt.LastSfam));
+ DEBUG ((EFI_D_INFO, " PFAT:: PPDT : SfamData[64] :\n"));
+ //
+ // Change the array size according to MAX_SFAM_COUNT
+ //
+ for (Index = 0; Index < 64; Index++) {
+ if ((Index == 15) || (Index == 31) || (Index == 47) || (Index == 63) ) {
+ DEBUG ((EFI_D_INFO, " 0x%X\n", SecurityConfig->PfatConfig->Ppdt.SfamData[Index]));
+ } else {
+ DEBUG ((EFI_D_INFO, " 0x%X ,", SecurityConfig->PfatConfig->Ppdt.SfamData[Index]));
+ }
+ }
+ DEBUG ((EFI_D_INFO, " \n"));
+ DEBUG ((EFI_D_INFO, " PFAT:: PpdtHash[4] : 0x%lX , 0x%lX , 0x%lX , 0x%lX \n", SecurityConfig->PfatConfig->PpdtHash[0], \
+ SecurityConfig->PfatConfig->PpdtHash[1], \
+ SecurityConfig->PfatConfig->PpdtHash[2], \
+ SecurityConfig->PfatConfig->PpdtHash[3]));
+
+ DEBUG ((EFI_D_INFO, " PFAT:: NumSpiComponents : 0x%x\n", SecurityConfig->PfatConfig->NumSpiComponents));
+ DEBUG ((EFI_D_INFO, " PFAT:: PPDT : ComponentSize[8] :\n"));
+ for (Index = 0; Index < SecurityConfig->PfatConfig->NumSpiComponents; Index++) {
+ if (Index == 7) {
+ DEBUG ((EFI_D_INFO, " 0x%X\n", SecurityConfig->PfatConfig->ComponentSize[Index]));
+ } else {
+ DEBUG ((EFI_D_INFO, " 0x%X ,", SecurityConfig->PfatConfig->ComponentSize[Index]));
+ }
+ }
+ DEBUG ((EFI_D_INFO, " \n"));
+ DEBUG ((EFI_D_INFO, " PFAT:: PfatMemSize : 0x%X\n", SecurityConfig->PfatConfig->PfatMemSize));
+ DEBUG ((EFI_D_INFO, " PFAT:: EcCmdDiscovery : 0x%X\n", SecurityConfig->PfatConfig->EcCmdDiscovery));
+ DEBUG ((EFI_D_INFO, " PFAT:: EcCmdProvisionEav : 0x%X\n", SecurityConfig->PfatConfig->EcCmdProvisionEav));
+ DEBUG ((EFI_D_INFO, " PFAT:: EcCmdLock : 0x%X\n", SecurityConfig->PfatConfig->EcCmdLock));
+ DEBUG ((EFI_D_INFO, " PFAT:: PFATLOG:: Version : 0x%X\n", SecurityConfig->PfatConfig->PfatLog.Version));
+ DEBUG ((EFI_D_INFO, " PFAT:: PFATLOG:: LastPage : 0x%X\n", SecurityConfig->PfatConfig->PfatLog.LastPage));
+ DEBUG ((EFI_D_INFO, " PFAT:: PFATLOG:: LoggingOptions : 0x%X\n", SecurityConfig->PfatConfig->PfatLog.LoggingOptions));
+ DEBUG ((EFI_D_INFO, " PFAT:: PFATLOG:: PfatModSvn : 0x%X\n", SecurityConfig->PfatConfig->PfatLog.PfatModSvn));
+ DEBUG ((EFI_D_INFO, " PFAT:: PFATLOG:: NumOfEntriesInLog : 0x%X\n", SecurityConfig->PfatConfig->PfatLog.NumOfEntriesInLog));
+ //
+ // SECURITY_CONFIG : TXT_CONFIG
+ //
+#if defined(TXT_SUPPORT_FLAG) && (TXT_SUPPORT_FLAG == 1)
+ DEBUG ((EFI_D_INFO, " TXT:: SinitMemorySize : 0x%lX\n", SecurityConfig->TxtConfig->SinitMemorySize));
+ DEBUG ((EFI_D_INFO, " TXT:: TxtHeapMemorySize : 0x%lX\n", SecurityConfig->TxtConfig->TxtHeapMemorySize));
+ DEBUG ((EFI_D_INFO, " TXT:: TxtDprMemoryBase : 0x%lX\n", SecurityConfig->TxtConfig->TxtDprMemoryBase));
+ DEBUG ((EFI_D_INFO, " TXT:: TxtDprMemorySize : 0x%lX\n", SecurityConfig->TxtConfig->TxtDprMemorySize));
+ DEBUG ((EFI_D_INFO, " TXT:: BiosAcmBase : 0x%lX\n", SecurityConfig->TxtConfig->BiosAcmBase));
+ DEBUG ((EFI_D_INFO, " TXT:: BiosAcmSize : 0x%lX\n", SecurityConfig->TxtConfig->BiosAcmSize));
+ DEBUG ((EFI_D_INFO, " TXT:: McuUpdateDataAddr : 0x%lX\n", SecurityConfig->TxtConfig->McuUpdateDataAddr));
+ DEBUG ((EFI_D_INFO, " TXT:: TgaSize : 0x%lX\n", SecurityConfig->TxtConfig->TgaSize));
+ DEBUG ((EFI_D_INFO, " TXT:: TxtLcpPdBase : 0x%lX\n", SecurityConfig->TxtConfig->TxtLcpPdBase));
+ DEBUG ((EFI_D_INFO, " TXT:: TxtLcpPdSize : 0x%lX\n", SecurityConfig->TxtConfig->TxtLcpPdSize));
+#else
+ DEBUG ((EFI_D_INFO, " TXT CONFIG:: UNSUPPORTED \n"));
+#endif
+
+ //
+ // OVERCLOCKING_CONFIG
+ //
+ DEBUG ((EFI_D_INFO, " OC:: CoreVoltageOffset : 0x%X\n", OverclockingConfig->CoreVoltageOffset));
+ DEBUG ((EFI_D_INFO, " OC:: CoreVoltageOverride : 0x%X\n", OverclockingConfig->CoreVoltageOverride));
+ DEBUG ((EFI_D_INFO, " OC:: CoreExtraTurboVoltage : 0x%X\n", OverclockingConfig->CoreExtraTurboVoltage));
+ DEBUG ((EFI_D_INFO, " OC:: CoreMaxOcTurboRatio : 0x%X\n", OverclockingConfig->CoreMaxOcTurboRatio));
+ DEBUG ((EFI_D_INFO, " OC:: ClrVoltageOffset : 0x%X\n", OverclockingConfig->ClrVoltageOffset));
+ DEBUG ((EFI_D_INFO, " OC:: ClrVoltageOverride : 0x%X\n", OverclockingConfig->ClrVoltageOverride));
+ DEBUG ((EFI_D_INFO, " OC:: ClrExtraTurboVoltage : 0x%X\n", OverclockingConfig->ClrExtraTurboVoltage));
+ DEBUG ((EFI_D_INFO, " OC:: ClrMaxOcTurboRatio : 0x%X\n", OverclockingConfig->ClrMaxOcTurboRatio));
+ DEBUG ((EFI_D_INFO, " OC:: SvidVoltageOverride : 0x%X\n", OverclockingConfig->SvidVoltageOverride));
+ DEBUG ((EFI_D_INFO, " OC:: SvidEnable : 0x%X\n", OverclockingConfig->SvidEnable));
+ DEBUG ((EFI_D_INFO, " OC:: FivrFaultsEnable : 0x%X\n", OverclockingConfig->FivrFaultsEnable));
+ DEBUG ((EFI_D_INFO, " OC:: FivrEfficiencyEnable : 0x%X\n", OverclockingConfig->FivrEfficiencyEnable));
+ DEBUG ((EFI_D_INFO, " OC:: CoreVoltageMode : 0x%X\n", OverclockingConfig->CoreVoltageMode));
+ DEBUG ((EFI_D_INFO, " OC:: ClrVoltageMode : 0x%X\n", OverclockingConfig->ClrVoltageMode));
+ DEBUG ((EFI_D_INFO, " OC:: OcSupport : 0x%X\n", OverclockingConfig->OcSupport));
+
+ DEBUG ((EFI_D_INFO, "\n------------------------ CpuPlatformPolicyPpi Dump End -----------------\n\n"));
+#endif
+}
diff --git a/ReferenceCode/Haswell/CpuInit/Pei/CpuInitPeim.dxs b/ReferenceCode/Haswell/CpuInit/Pei/CpuInitPeim.dxs
new file mode 100644
index 0000000..62f855b
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Pei/CpuInitPeim.dxs
@@ -0,0 +1,42 @@
+/** @file
+ Dependency expression source file.
+
+@copyright
+ Copyright (c) 2004 - 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
+
+**/
+
+
+//
+// Common for R8 and R9 codebase
+//
+#include "AutoGen.h"
+#include "PeimDepex.h"
+
+//
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are both "defined" in R8 codebase;
+// BUILD_WITH_EDKII_GLUE_LIB is defined in Edk-Dev-Snapshot-20070228 and later version
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are "not defined" in R9 codebase.
+//
+#if defined (BUILD_WITH_GLUELIB) || defined (BUILD_WITH_EDKII_GLUE_LIB)
+#include "EfiDepex.h"
+#include EFI_PPI_DEFINITION (CpuPlatformPolicy)
+#endif
+
+DEPENDENCY_START
+
+ PEI_CPU_PLATFORM_POLICY_PPI_GUID
+
+DEPENDENCY_END
diff --git a/ReferenceCode/Haswell/CpuInit/Pei/CpuInitPeim.h b/ReferenceCode/Haswell/CpuInit/Pei/CpuInitPeim.h
new file mode 100644
index 0000000..9d6fac5
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Pei/CpuInitPeim.h
@@ -0,0 +1,212 @@
+/** @file
+ Describes the functions visible to the rest of the CpuPeim.
+
+@copyright
+ Copyright (c) 2010 - 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 an 'Intel Pre-EFI 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
+**/
+#ifndef _CPU_INIT_PEIM_H_
+#define _CPU_INIT_PEIM_H_
+
+#include EFI_PPI_PRODUCER (Cache)
+#include EFI_PPI_DEFINITION (CpuPlatformPolicy)
+#include "CpuRegs.h"
+
+typedef struct {
+ UINT32 HtDisabled : 1;
+ UINT32 NumberOfActiveCores : 2;
+ UINT32 Reserved0 : 2;
+ UINT32 Bist : 1;
+ UINT32 FlexRatio : 6;
+ UINT32 Reserved1 : 4;
+ UINT32 Reserved2 : 16;
+} CPU_STRAP_SET;
+
+typedef UINT32 CPU_RESET_TYPE;
+
+typedef struct {
+ UINT64 MsrValue;
+ BOOLEAN Changed;
+} MTRR_VALUE;
+
+typedef struct {
+ PEI_CACHE_PPI Ppi;
+ EFI_PEI_PPI_DESCRIPTOR PpiDesc;
+ MTRR_VALUE FixedMtrrValue[V_FIXED_MTRR_NUMBER];
+ MTRR_VALUE VariableMtrrValue[V_MAXIMUM_VARIABLE_MTRR_NUMBER * 2];
+ BOOLEAN FixedMtrrChanged;
+ BOOLEAN VariableMtrrChanged;
+ BOOLEAN NemDisabledDone;
+} CACHE_PPI_INSTANCE;
+
+#define PEI_CACHE_PPI_INSTANCE_FROM_THIS(a) _CR (a, CACHE_PPI_INSTANCE, Ppi)
+
+///
+/// Breaking UINT64 MSR into DWORDs/BYTEs
+///
+#pragma pack(1)
+typedef union _MSR_REGISTER {
+ UINT64 Qword;
+
+ struct _DWORDS {
+ UINT32 Low;
+ UINT32 High;
+ } Dwords;
+
+ struct _BYTES {
+ UINT8 FirstByte;
+ UINT8 SecondByte;
+ UINT8 ThirdByte;
+ UINT8 FouthByte;
+ UINT8 FifthByte;
+ UINT8 SixthByte;
+ UINT8 SeventhByte;
+ UINT8 EighthByte;
+ } Bytes;
+
+} MSR_REGISTER;
+#pragma pack()
+#define NO_RESET 0
+#define CPU_ONLY_RESET 1
+#define WARM_RESET 2
+#define COLDRESET 3
+
+#define RESET_PPI_WARM_RESET 0
+#define RESET_PPI_COLD_RESET 3
+
+#define RESET_PORT 0x0CF9
+#define CLEAR_RESET_BITS 0x0F1
+#define PSIX_THRESHOLD_MASK 0x3FFFFFFF ///< Bits 61:32 - Mask value respect to Dword.High
+#define PSI1_THRESHOLD_VALUE 0x14
+#define PSI2_THRESHOLD_VALUE 0x05
+#define PSI3_THRESHOLD_VALUE 0x01
+
+#define MAX_OVERCLOCKING_BINS 0x7
+
+/**
+ Set up flags in CR4 for XMM instruction enabling
+**/
+VOID
+XmmInit (
+ VOID
+ );
+
+/**
+ Loads the Processor Microcode & Install the Cache PPI
+
+ @param[in] FfsHeader - Pointer to an alleged FFS file.
+ @param[in] PeiServices - General purpose services available to every PEIM.
+
+ @retval EFI_STATUS - the status code returned from any sub-routine
+**/
+EFI_STATUS
+PeimInitializeCpu (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices
+ );
+
+/**
+ Install CacheInitPpi
+
+ @retval EFI_OUT_OF_RESOURCES - failed to allocate required pool
+**/
+EFI_STATUS
+CacheInitPpiInit (
+ VOID
+ );
+
+/**
+ Set CPU strap setting for feature change
+
+ @param[in] PeiServices - Indirect reference to the PEI Services Table.
+ @param[in] NotifyDescriptor - Address of the notification descriptor data structure. Type
+ EFI_PEI_NOTIFY_DESCRIPTOR is defined above.
+ @param[in] Ppi - Address of the PPI that was installed.
+
+ @retval EFI_SUCCESS - Function completed successfully
+**/
+EFI_STATUS
+EFIAPI
+SetCpuStrap (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ );
+
+/**
+ Based on ResetType, perform warm or cold reset using PCH Reset PPI
+
+ @param[in] PeiServices - Indirect reference to the PEI Services Table.
+ @param[in] ResetType - CPU_RESET_TYPE to indicate which reset shoudl be performed.
+
+ @exception EFI_UNSUPPORTED - Reset type unsupported
+ @retval EFI_SUCCESS - function successfully (system should already reset)
+**/
+EFI_STATUS
+PerformWarmORColdReset (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN CPU_RESET_TYPE ResetType
+ );
+
+/**
+ Based on ResetType, perform warm or cold reset using PCH Reset PPI
+
+ @param[in] PeiServices
+ @param[in] CPU_RESET_TYPE
+
+ @retval EFI_STATUS
+
+ Build BIST HOB
+
+ @param[in] PeiServices - Indirect reference to the PEI Services Table.
+ @param[in] NotifyDescriptor - Address of the notification descriptor data structure. Type
+ EFI_PEI_NOTIFY_DESCRIPTOR is defined above.
+ @param[in] Ppi - Address of the PPI that was installed.
+
+ @retval EFI_SUCCESS - Hob built or not necessary
+**/
+EFI_STATUS
+EFIAPI
+BuildBistHob (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ );
+
+/**
+ Dump RC CPU and PPM platform policies
+
+ @param[in] CpuPlatformPolicyPpi - Address of the cpu platform policy ppi.
+**/
+VOID
+CpuPeiPolicyDump(
+ IN PEI_CPU_PLATFORM_POLICY_PPI *CpuPlatformPolicyPpi
+ );
+
+/**
+
+ Perform the platform spefific initializations.
+
+ @param[in] PeiServices - Indirect reference to the PEI Services Table.
+ @param[in] CpuPlatformPolicyPpi - Platform Policy PPI
+
+**/
+VOID
+BootGuardInit (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_CPU_PLATFORM_POLICY_PPI *CpuPlatformPolicyPpi
+ );
+
+#endif
diff --git a/ReferenceCode/Haswell/CpuInit/Pei/CpuInitPeim.inf b/ReferenceCode/Haswell/CpuInit/Pei/CpuInitPeim.inf
new file mode 100644
index 0000000..6110b72
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Pei/CpuInitPeim.inf
@@ -0,0 +1,124 @@
+#
+# This file contains an 'Intel Pre-EFI 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
+#
+#/*++
+#
+# Copyright (c) 2007 - 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.
+
+#
+# Module Name:
+#
+# CpuInitPeim.inf
+#
+# Abstract:
+#
+# Component description file for CPU module
+#
+#
+#--*/
+
+[defines]
+BASE_NAME = CpuInitPeim
+FILE_GUID = 01359D99-9446-456d-ADA4-50A711C03ADA
+COMPONENT_TYPE = PE32_PEIM
+
+[sources.common]
+ CpuInitPeim.c
+ CachePeim.c
+ PfatInit.c
+ CpuOcInit.c
+ BootGuardInit.c
+
+#
+# Edk II Glue Driver Entry Point
+#
+ EdkIIGluePeimEntryPoint.c
+
+[sources.ia32]
+ Ia32/Cpu.asm
+
+[includes.common]
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Pei/Include
+ $(EDK_SOURCE)/Foundation/Cpu/Pentium/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include
+#
+# Edk II Glue Library, some hearder are included by R9 header so have to include
+#
+ $(EFI_SOURCE)
+ $(EFI_SOURCE)/Framework
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Library/OverclockingLib
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include/Library
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/SampleCode
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/SampleCode/Include
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library
+ $(EFI_SOURCE)/$(PROJECT_SA_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_SA_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_ME_ROOT)/Library/MeKernel/Include
+ $(EFI_SOURCE)/$(PROJECT_ME_ROOT)/Heci/Include
+
+[libraries.common]
+ EdkFrameworkPpiLib
+ EdkIIGlueBaseLib
+ EdkIIGlueBaseMemoryLib
+ EdkIIGluePeiDebugLibReportStatusCode
+ EdkIIGluePeiReportStatusCodeLib
+ EdkIIGluePeiServicesLib
+ EdkIIGluePeiMemoryAllocationLib
+ EdkIIGluePeiHobLib
+ EdkPpiLib
+ CpuPpiLib
+ CpuGuidLib
+ $(PROJECT_PCH_FAMILY)PpiLib
+ PeiKscLib
+ CpuPlatformLib
+ OverclockingLib
+ BootGuardLib
+
+[libraries.ia32]
+ CpuIA32Lib
+
+[nmake.common]
+ IMAGE_ENTRY_POINT = _ModuleEntryPoint
+ DPX_SOURCE = CpuInitPeim.dxs
+
+#
+# Module Entry Point
+#
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=PeimInitializeCpu
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_BASE_LIB__ \
+ -D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ -D __EDKII_GLUE_PEI_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ -D __EDKII_GLUE_PEI_REPORT_STATUS_CODE_LIB__ \
+ -D __EDKII_GLUE_PEI_SERVICES_LIB__
diff --git a/ReferenceCode/Haswell/CpuInit/Pei/CpuOcInit.c b/ReferenceCode/Haswell/CpuInit/Pei/CpuOcInit.c
new file mode 100644
index 0000000..8aa7cd7
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Pei/CpuOcInit.c
@@ -0,0 +1,292 @@
+/** @file
+ OC CPU Early Post initializations.
+
+@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
+
+**/
+
+///
+/// External include files do NOT need to be explicitly specified in real EDKII
+/// environment
+///
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGluePeim.h"
+#include "CpuInitPeim.h"
+#include "CpuAccess.h"
+#include "OverclockingLibrary.h"
+#include "CpuOcInit.h"
+#endif
+
+/**
+ Initializes Overclocking settings in the processor.
+
+ @param[in] PeiServices - General purpose services available to every PEIM.
+ @param[in] OverclockingtConfig Pointer to Policy protocol instance
+
+ @retval EFI_SUCCESS
+**/
+EFI_STATUS
+CpuOcInit (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_CPU_PLATFORM_POLICY_PPI *CpuPlatformPolicyPpi
+ )
+{
+ EFI_STATUS Status;
+ OC_CAPABILITIES_ITEM OcCaps;
+ VOLTAGE_FREQUENCY_ITEM CurrentVfItem;
+ VOLTAGE_FREQUENCY_ITEM RequestedVfItem;
+ GLOBAL_CONFIG_ITEM CurrentFivrItem;
+ GLOBAL_CONFIG_ITEM RequestedFivrItem;
+ SVID_CONFIG_ITEM CurrentSvidItem;
+ SVID_CONFIG_ITEM RequestedSvidItem;
+ UINT32 LibStatus;
+ UINT8 DomainId;
+ UINT8 ResetRequired;
+ WDT_PPI *gWdtPei;
+
+ LibStatus = 0; //DEBUG
+ ResetRequired = FALSE;
+ if (CpuPlatformPolicyPpi->OverclockingConfig->OcSupport == 0) {
+ ///
+ /// Overclocking is disabled
+ ///
+ DEBUG ((EFI_D_ERROR, "(OC) Overclocking is disabled. Bypassing CPU core overclocking flow.\n"));
+ return EFI_SUCCESS;
+ }
+
+ Status = EFI_SUCCESS;
+ ZeroMem(&CurrentFivrItem,sizeof(CurrentFivrItem));
+ ZeroMem(&RequestedFivrItem,sizeof(RequestedFivrItem));
+ ZeroMem(&CurrentSvidItem,sizeof(CurrentSvidItem));
+ ZeroMem(&RequestedSvidItem,sizeof(RequestedSvidItem));
+
+ //
+ // Locate WDT_PPI (ICC WDT PPI)
+ //
+ Status = PeiServicesLocatePpi (
+ &gWdtPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &gWdtPei
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// We will loop on the CPU domains to manage the voltage/frequency settings
+ ///
+ for (DomainId = OC_LIB_DOMAIN_ID_IA_CORE; DomainId < OC_LIB_DOMAIN_ID_UNCORE; DomainId++) {
+ ///
+ /// Only IA_CORE and CLR are valid for CPU Core
+ ///
+ if ((DomainId == OC_LIB_DOMAIN_ID_IA_CORE) || (DomainId == OC_LIB_DOMAIN_ID_CLR)) {
+
+ ///
+ /// Get OC Capabilities of the domain
+ ///
+ ZeroMem(&OcCaps,sizeof(OcCaps));
+ OcCaps.DomainId = DomainId;
+ Status = GetOcCapabilities(&OcCaps,&LibStatus);
+
+ if (LibStatus == OC_LIB_COMPLETION_CODE_SUCCESS) {
+ ///
+ /// If any OC is supported on this domain, then proceed
+ ///
+ if (OcCaps.RatioOcSupported || OcCaps.VoltageOverridesSupported || OcCaps.VoltageOffsetSupported) {
+ ///
+ /// Need to populate the user requested settings from the platform policy
+ /// to determine if OC changes are desired.
+ ///
+ ZeroMem(&CurrentVfItem,sizeof(CurrentVfItem));
+ CurrentVfItem.DomainId = DomainId;
+
+ ///
+ /// Get a copy of the current domain VfSettings from the Mailbox Library
+ ///
+ Status = GetVoltageFrequencyItem(&CurrentVfItem,&LibStatus);
+ if ((Status != EFI_SUCCESS) || (LibStatus != OC_LIB_COMPLETION_CODE_SUCCESS)) {
+ continue;
+ }
+
+ ///
+ /// Populate the user requested VfSettings struct
+ ///
+ ZeroMem(&RequestedVfItem,sizeof(RequestedVfItem));
+ RequestedVfItem.DomainId = DomainId;
+ if (DomainId == OC_LIB_DOMAIN_ID_IA_CORE) {
+ RequestedVfItem.VfSettings.MaxOcRatio = (UINT8) CpuPlatformPolicyPpi->OverclockingConfig->CoreMaxOcTurboRatio;
+ } else if (DomainId == OC_LIB_DOMAIN_ID_CLR) {
+ RequestedVfItem.VfSettings.MaxOcRatio = (UINT8) CpuPlatformPolicyPpi->OverclockingConfig->ClrMaxOcTurboRatio;
+ }
+
+ ///
+ /// VoltageTarget has 2 uses and we need to update the target based
+ /// on the voltagemode requested
+ ///
+ if (DomainId == OC_LIB_DOMAIN_ID_IA_CORE) {
+ RequestedVfItem.VfSettings.VoltageTargetMode = CpuPlatformPolicyPpi->OverclockingConfig->CoreVoltageMode;
+ if (RequestedVfItem.VfSettings.VoltageTargetMode == OC_LIB_OFFSET_ADAPTIVE) {
+ RequestedVfItem.VfSettings.VoltageTarget = CpuPlatformPolicyPpi->OverclockingConfig->CoreExtraTurboVoltage;
+ } else {
+ RequestedVfItem.VfSettings.VoltageTarget = CpuPlatformPolicyPpi->OverclockingConfig->CoreVoltageOverride;
+ }
+ RequestedVfItem.VfSettings.VoltageOffset = CpuPlatformPolicyPpi->OverclockingConfig->CoreVoltageOffset;
+ } else if (DomainId == OC_LIB_DOMAIN_ID_CLR) {
+ RequestedVfItem.VfSettings.VoltageTargetMode = CpuPlatformPolicyPpi->OverclockingConfig->ClrVoltageMode;
+ if (RequestedVfItem.VfSettings.VoltageTargetMode == OC_LIB_OFFSET_ADAPTIVE) {
+ RequestedVfItem.VfSettings.VoltageTarget = CpuPlatformPolicyPpi->OverclockingConfig->ClrExtraTurboVoltage;
+ } else {
+ RequestedVfItem.VfSettings.VoltageTarget = CpuPlatformPolicyPpi->OverclockingConfig->ClrVoltageOverride;
+ }
+ RequestedVfItem.VfSettings.VoltageOffset = CpuPlatformPolicyPpi->OverclockingConfig->ClrVoltageOffset;
+ }
+
+ ///
+ /// Compare current settings with user requested settings to see if changes are needed
+ ///
+ if (CompareMem((VOID *)&RequestedVfItem,(VOID *)&CurrentVfItem,sizeof(VOLTAGE_FREQUENCY_ITEM))) {
+ ///
+ /// Arm watchdog timer for OC changes
+ ///
+ Status = gWdtPei->ReloadAndStart (WDT_TIMEOUT_BETWEEN_PEI_DXE);
+
+ ///
+ /// Need to update the requested voltage/frequency values
+ ///
+ DEBUG ((EFI_D_INFO, "(OC) Set Voltage Frequency for Domain = %X\n", DomainId));
+ DEBUG ((EFI_D_INFO, "(OC) RequestedVfItem.VfSettings.MaxOcRatio = %X\n", RequestedVfItem.VfSettings.MaxOcRatio));
+ DEBUG ((EFI_D_INFO, "(OC) RequestedVfItem.VfSettings.TargetMode = %X\n", RequestedVfItem.VfSettings.VoltageTargetMode));
+ DEBUG ((EFI_D_INFO, "(OC) RequestedVfItem.VfSettings.VoltageTarget = %X\n", RequestedVfItem.VfSettings.VoltageTarget));
+ DEBUG ((EFI_D_INFO, "(OC) RequestedVfItem.VfSettings.VoltageOffset = %X\n", RequestedVfItem.VfSettings.VoltageOffset));
+ DEBUG ((EFI_D_INFO, "(OC) CurrentVfItem.VfSettings.MaxOcRatio = %X\n", CurrentVfItem.VfSettings.MaxOcRatio));
+ DEBUG ((EFI_D_INFO, "(OC) CurrentVfItem.VfSettings.TargetMode = %X\n", CurrentVfItem.VfSettings.VoltageTargetMode));
+ DEBUG ((EFI_D_INFO, "(OC) CurrentVfItem.VfSettings.VoltageTarget = %X\n", CurrentVfItem.VfSettings.VoltageTarget));
+ DEBUG ((EFI_D_INFO, "(OC) CurrentVfItem.VfSettings.VoltageOffset = %X\n", CurrentVfItem.VfSettings.VoltageOffset));
+ Status = SetVoltageFrequencyItem(RequestedVfItem,&LibStatus);
+ if ((Status != EFI_SUCCESS) || (LibStatus != OC_LIB_COMPLETION_CODE_SUCCESS)) {
+ DEBUG ((EFI_D_ERROR, "(OC) Set Voltage Frequency failed. EFI Status = %X, Library Status = %X\n", Status, LibStatus));
+ }
+ }
+ }
+ } else {
+ DEBUG ((EFI_D_ERROR, "(OC) GetOcCapabilities message failed. Library Status = %X, Domain = %X\n", LibStatus, DomainId));
+ }
+ }
+ }
+
+ ///
+ /// Detect changes to global FIVR settings
+ ///
+ Status = GetFivrConfig(&CurrentFivrItem,&LibStatus);
+
+ if (LibStatus == OC_LIB_COMPLETION_CODE_SUCCESS) {
+ ///
+ /// Populate the requested FIVR settings from platform policy. The platform policy defines
+ /// these bits as 0-Disabled, 1-Enabled. The Mailbox uses the reverse encoding. Need to convert
+ /// the platform policy data to match the mailbox input.
+ ///
+ RequestedFivrItem.DisableFivrFaults = (~CpuPlatformPolicyPpi->OverclockingConfig->FivrFaultsEnable) & BIT0_MASK;
+ RequestedFivrItem.DisableFivrEfficiency = (~CpuPlatformPolicyPpi->OverclockingConfig->FivrEfficiencyEnable) & BIT0_MASK;
+
+ ///
+ /// Compare current FIVR settings with requested FIVR settings to see if changes are needed
+ ///
+ if (CompareMem((VOID *)&RequestedFivrItem,(VOID *)&CurrentFivrItem,sizeof(GLOBAL_CONFIG_ITEM))) {
+ ///
+ /// Arm watchdog timer for OC changes
+ ///
+ Status = gWdtPei->ReloadAndStart (8);
+
+ ///
+ /// Need to update the requested FIVR values
+ ///
+ DEBUG ((EFI_D_INFO, "(OC) Set FIVR Config for Domain = %X\n", DomainId));
+ Status = SetFivrConfig(RequestedFivrItem, &LibStatus);
+ if ((Status != EFI_SUCCESS) || (LibStatus != OC_LIB_COMPLETION_CODE_SUCCESS)) {
+ DEBUG ((EFI_D_ERROR, "(OC) Set FIVR Config failed. EFI Status = %X, Library Status = %X\n", Status, LibStatus));
+ }
+ else {
+ ///
+ /// If Re-enabling Fivr Faults, system needs to perform a cold reset for hardware to take effect
+ ///
+ if ((CurrentFivrItem.DisableFivrFaults == 1) && (RequestedFivrItem.DisableFivrFaults == 0)) {
+ DEBUG ((EFI_D_ERROR, "(OC) FIVR Faults enable detected. Cold Reset required.\n"));
+ ResetRequired = TRUE;
+ }
+ }
+ }
+ }
+ else {
+ DEBUG ((EFI_D_ERROR, "(OC) Get FIVR Config message failed. Library Status = %X\n", LibStatus));
+ }
+
+ ///
+ /// Detect changes to SVID settings
+ ///
+ Status = GetSvidConfig(&CurrentSvidItem,&LibStatus);
+
+ if (LibStatus == OC_LIB_COMPLETION_CODE_SUCCESS) {
+ ///
+ /// Populate the requested SVID settings from platform policy. SvidDisable uses a
+ /// reverse encoding from the platform policy defintion and will need to be converted.
+ ///
+ RequestedSvidItem.VoltageTarget = CpuPlatformPolicyPpi->OverclockingConfig->SvidVoltageOverride;
+ RequestedSvidItem.SvidDisable = ~(CpuPlatformPolicyPpi->OverclockingConfig->SvidEnable) & BIT0_MASK;
+
+ ///
+ /// Compare current SVID settings with requested SVID settings to see if changes are needed
+ ///
+ if (CompareMem((VOID *)&RequestedSvidItem,(VOID *)&CurrentSvidItem,sizeof(SVID_CONFIG_ITEM))) {
+ ///
+ /// Arm watchdog timer for OC changes
+ ///
+ Status = gWdtPei->ReloadAndStart (8);
+
+ ///
+ /// If Re-enabling SVID, system needs to perform a cold reset for hardware to take effect. No write to mailbox needed.
+ ///
+ if ((CurrentSvidItem.SvidDisable == 1) && (RequestedSvidItem.SvidDisable == 0)) {
+ DEBUG ((EFI_D_ERROR, "(OC) SVID Enable detected. Cold Reset required.\n"));
+ ResetRequired = TRUE;
+ }
+ else {
+ ///
+ /// Need to update the requested SVID values
+ ///
+ DEBUG ((EFI_D_INFO, "(OC) Set SVID Config for Domain = %X\n", DomainId));
+ Status = SetSvidConfig(RequestedSvidItem, &LibStatus);
+ if ((Status != EFI_SUCCESS) || (LibStatus != OC_LIB_COMPLETION_CODE_SUCCESS)) {
+ DEBUG ((EFI_D_ERROR, "(OC) Set SVID Config failed. EFI Status = %X, Library Status = %X\n", Status, LibStatus));
+ }
+ }
+ }
+ } else {
+ DEBUG ((EFI_D_ERROR, "(OC) GetFivrConfig message failed. Library Status = %X\n", LibStatus));
+ }
+
+ ///
+ /// Command was successful and SVID config has changed. CPU must perform a reset
+ /// for SVID settings to take effect.
+ ///
+ if (ResetRequired) {
+ DEBUG ((EFI_D_ERROR, "(OC) Perform Cold Reset\n"));
+ PerformWarmORColdReset (PeiServices, COLDRESET);
+ }
+
+ return Status;
+}
+
diff --git a/ReferenceCode/Haswell/CpuInit/Pei/CpuOcInit.h b/ReferenceCode/Haswell/CpuInit/Pei/CpuOcInit.h
new file mode 100644
index 0000000..652c67e
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Pei/CpuOcInit.h
@@ -0,0 +1,55 @@
+/** @file
+ Describes the functions visible to the rest of the OcInit.
+
+@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
+**/
+#ifndef _OC_INIT_H_
+#define _OC_INIT_H_
+
+#include "OverclockingLibrary.h"
+#include EFI_PPI_DEFINITION (CpuPlatformPolicy)
+#include EFI_PPI_CONSUMER (Wdt)
+
+#ifdef USE_WDT_IN_DEBUG_BIOS
+//
+// MRC takes a lot of time to execute in debug mode
+//
+#define WDT_TIMEOUT_BETWEEN_PEI_DXE 120
+#else
+#define WDT_TIMEOUT_BETWEEN_PEI_DXE 60
+#endif
+
+///
+/// Function Prototypes
+///
+/**
+ Initializes Overclocking settings in the processor.
+
+ @param[in] PeiServices - General purpose services available to every PEIM.
+ @param[in] OverclockingtConfig Pointer to Policy protocol instance
+
+ @retval EFI_SUCCESS
+**/
+EFI_STATUS
+CpuOcInit (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_CPU_PLATFORM_POLICY_PPI *CpuPlatformPolicyPpi
+ );
+
+#endif
+
diff --git a/ReferenceCode/Haswell/CpuInit/Pei/Ia32/Cpu.asm b/ReferenceCode/Haswell/CpuInit/Pei/Ia32/Cpu.asm
new file mode 100644
index 0000000..e7c812a
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Pei/Ia32/Cpu.asm
@@ -0,0 +1,77 @@
+;
+; This file contains an 'Intel Pre-EFI 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
+;
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2006 - 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.
+;
+;
+; Module Name:
+;
+; Cpu.asm
+;
+; Abstract:
+;
+; Assembly code of Cpu
+;
+;------------------------------------------------------------------------------
+
+ .686p
+ .model flat
+ .xmm
+
+IA32_CR4_OSFXSR equ 200h
+IA32_CR4_OSXMMEXCPT equ 400h
+IA32_CR0_MP equ 2h
+
+IA32_CPUID_SSE2 equ 02000000h
+IA32_CPUID_SSE2_B equ 26
+
+ .code
+
+;------------------------------------------------------------------------------
+; Set up flags in CR4 for XMM instruction enabling
+;------------------------------------------------------------------------------
+XmmInit PROC C PUBLIC
+ push ebx
+
+ ; Check whether SSE2 is supported
+ mov eax, 1
+ cpuid
+ bt edx, IA32_CPUID_SSE2_B
+ jnc @F
+
+ ; Enable XMM
+ mov eax, cr0
+ or eax, IA32_CR0_MP
+ mov cr0, eax
+ mov eax, cr4
+ or eax, IA32_CR4_OSFXSR OR IA32_CR4_OSXMMEXCPT
+ mov cr4, eax
+
+@@:
+ pop ebx
+ ret
+XmmInit ENDP
+
+
+;------------------------------------------------------------------------------
+; Invalidate cache
+;------------------------------------------------------------------------------
+CacheInvd PROC C PUBLIC
+ invd
+ ret
+CacheInvd ENDP
+
+ END
diff --git a/ReferenceCode/Haswell/CpuInit/Pei/PfatInit.c b/ReferenceCode/Haswell/CpuInit/Pei/PfatInit.c
new file mode 100644
index 0000000..8eff986
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Pei/PfatInit.c
@@ -0,0 +1,191 @@
+/** @file
+ PFAT EarlyPost initializations.
+
+@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
+**/
+
+///
+/// External include files do NOT need to be explicitly specified in real EDKII
+/// environment
+///
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGluePeim.h"
+#include "CpuInitPeim.h"
+#include "CpuAccess.h"
+#include "PfatInit.h"
+#ifdef PFAT_EC_FLAG
+#include EFI_PPI_DEPENDENCY (CpuIo)
+#include EFI_PPI_PRODUCER (Stall)
+#include "PeiKscLib.h"
+#endif //PFAT_EC_FLAG
+#endif
+
+#ifdef PFAT_EC_FLAG
+/**
+ Gets CPU's random number generator.
+
+ @param[out] UINT32 - Random value
+**/
+UINT32
+RandomNumber (
+ void
+ )
+{
+ UINT32 Random = 0;
+
+ ///
+ /// Assembly instruction to read CPU's random number generator
+ /// Instruction is only available 100k cycles after reset
+ ///
+ __asm {
+tryAgain:
+ ; rdrand eax
+ ; db 0Fh, 0C7h, 0F0h
+
+ _emit 0x0F
+ _emit 0xC7
+ _emit 0xF0
+
+ mov Random, eax
+ jnc tryAgain; CF will be set is valid number was generated
+ }
+
+ return (Random);
+}
+#endif //PFAT_EC_FLAG
+
+/**
+ Perform the platform spefific initializations.
+
+ @param[in] PeiServices - Indirect reference to the PEI Services Table.
+ @param[in] CpuPlatformPolicyPpi - Platform Policy PPI
+**/
+VOID
+PfatInit (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_CPU_PLATFORM_POLICY_PPI *CpuPlatformPolicyPpi
+ )
+{
+ EFI_STATUS Status;
+ UINT64 MsrValue;
+ BOOLEAN ResetRequired;
+ PFAT_HOB *PfatHobPtr;
+ EFI_GUID PfatHobGuid = PFAT_HOB_GUID;
+ UINT8 i;
+ PFAT_CONFIG *PfatConfig;
+#ifdef PFAT_EC_FLAG
+ volatile UINT32 EphemeralAuthValue;
+ UINT8 EcStatus;
+ PEI_STALL_PPI *StallPpi;
+ PEI_CPU_IO_PPI *CpuIo;
+#endif //PFAT_EC_FLAG
+
+ DEBUG ((EFI_D_INFO, "PfatInit\n"));
+
+ ResetRequired = FALSE;
+ MsrValue = AsmReadMsr64 (MSR_PLATFORM_INFO);
+ if (!(MsrValue & B_MSR_PLATFORM_INFO_PFAT_AVAIL)) {
+ DEBUG ((EFI_D_INFO, "PFAT Feature is not supported\n"));
+ return;
+ }
+
+ if (CpuPlatformPolicyPpi->CpuConfig->Pfat) {
+ DEBUG ((EFI_D_INFO, "PFAT Module is Enable\n"));
+ PfatConfig = CpuPlatformPolicyPpi->SecurityConfig->PfatConfig;
+ ///
+ /// Read PFAT Control Register
+ ///
+ MsrValue = AsmReadMsr64 (MSR_PLAT_FRMW_PROT_CTRL);
+ if (MsrValue & B_MSR_PLAT_FRMW_PROT_CTRL_LK) {
+ if (!(MsrValue & B_MSR_PLAT_FRMW_PROT_CTRL_EN)) {
+ ///
+ /// Reset required as the PFAT CTRL MSR is locked and needs to be toggled
+ ///
+ ResetRequired = TRUE;
+ }
+ } else {
+#ifdef PFAT_EC_FLAG
+ if ((PfatConfig->Ppdt.PlatAttr & EC_PRESENT) && (PfatConfig->Ppdt.PlatAttr & EC_PFAT_PROTECTED)) {
+ DEBUG ((EFI_D_INFO, "EC is Present and EC FW supports PFAT\n"));
+ CpuIo = (**PeiServices).CpuIo;
+ Status = (*PeiServices)->LocatePpi (PeiServices, &gPeiStallPpiGuid, 0, NULL, &StallPpi);
+ ASSERT_PEI_ERROR (PeiServices, Status);
+ Status = SendKscCommand (PeiServices, CpuIo, StallPpi, PfatConfig->EcCmdProvisionEav);
+ if (Status == EFI_SUCCESS) {
+ EphemeralAuthValue = RandomNumber ();
+ for (i = 0; (i < (sizeof (EphemeralAuthValue))); i++) {
+ Status = SendKscData (PeiServices, CpuIo, StallPpi, (UINT8) ((EphemeralAuthValue >> (i * 8)) & 0xFF));
+ }
+ Status = ReceiveKscData (PeiServices, CpuIo, StallPpi, &EcStatus);
+ if (EcStatus != 0) {
+ ResetRequired = TRUE;
+ }
+ AsmWriteMsr32 (MSR_PLAT_FRMW_PROT_PASSWD, EphemeralAuthValue);
+ EphemeralAuthValue = 0;
+ Status = SendKscCommand (PeiServices, CpuIo, StallPpi, PfatConfig->EcCmdLock);
+ }
+ }
+#endif //PFAT_EC_FLAG
+ AsmWriteMsr64 (MSR_PLAT_FRMW_PROT_HASH_0, PfatConfig->PpdtHash[0]);
+ AsmWriteMsr64 (MSR_PLAT_FRMW_PROT_HASH_1, PfatConfig->PpdtHash[1]);
+ AsmWriteMsr64 (MSR_PLAT_FRMW_PROT_HASH_2, PfatConfig->PpdtHash[2]);
+ AsmWriteMsr64 (MSR_PLAT_FRMW_PROT_HASH_3, PfatConfig->PpdtHash[3]);
+ MsrValue |= (B_MSR_PLAT_FRMW_PROT_CTRL_LK | B_MSR_PLAT_FRMW_PROT_CTRL_EN);
+ AsmWriteMsr64 (MSR_PLAT_FRMW_PROT_CTRL, MsrValue);
+ }
+ ///
+ /// Create PFAT HOB
+ ///
+ if (!ResetRequired) {
+ Status = (*PeiServices)->CreateHob (PeiServices, EFI_HOB_TYPE_GUID_EXTENSION, sizeof (PFAT_HOB), (VOID **) &PfatHobPtr);
+ PfatHobPtr->EfiHobGuidType.Name = PfatHobGuid;
+ CopyMem (&PfatHobPtr->Ppdt, &PfatConfig->Ppdt, PfatConfig->Ppdt.PpdtSize);
+ CopyMem (&PfatHobPtr->PupHeader, &PfatConfig->PupHeader, sizeof (PUP_HEADER));
+ CopyMem (&PfatHobPtr->PfatLog, &PfatConfig->PfatLog, sizeof (PFAT_LOG));
+ PfatHobPtr->NumSpiComponents = PfatConfig->NumSpiComponents;
+ for (i = 0; i < PfatConfig->NumSpiComponents; i++) {
+ PfatHobPtr->ComponentSize[i] = PfatConfig->ComponentSize[i];
+ }
+ }
+ } else {
+ DEBUG ((EFI_D_INFO, "PFAT Module is Disabled\n"));
+ MsrValue = AsmReadMsr64 (MSR_PLAT_FRMW_PROT_CTRL);
+ if (MsrValue & B_MSR_PLAT_FRMW_PROT_CTRL_LK) {
+ if (MsrValue & B_MSR_PLAT_FRMW_PROT_CTRL_EN) {
+ ///
+ /// Reset required as the PFAT CTRL MSR is locked and needs to be toggled
+ ///
+ ResetRequired = TRUE;
+ }
+ } else {
+ MsrValue &= ~B_MSR_PLAT_FRMW_PROT_CTRL_EN;
+ MsrValue |= B_MSR_PLAT_FRMW_PROT_CTRL_LK;
+ AsmWriteMsr64 (MSR_PLAT_FRMW_PROT_CTRL, MsrValue);
+ }
+ }
+
+ if (ResetRequired) {
+ ///
+ /// Perform Cold Reset
+ ///
+ DEBUG ((EFI_D_INFO, "Reset Required. Performing Cold Reset to unlock PFAT CONTROL MSR\n"));
+ PerformWarmORColdReset (PeiServices, COLDRESET);
+ }
+
+ return;
+}
diff --git a/ReferenceCode/Haswell/CpuInit/Pei/PfatInit.h b/ReferenceCode/Haswell/CpuInit/Pei/PfatInit.h
new file mode 100644
index 0000000..22e807f
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuInit/Pei/PfatInit.h
@@ -0,0 +1,42 @@
+/** @file
+ Describes the functions visible to the rest of the PfatInit.
+
+@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
+**/
+#ifndef _PFAT_INIT_H_
+#define _PFAT_INIT_H_
+
+#include "PfatDefinitions.h"
+#include EFI_PPI_DEFINITION (CpuPlatformPolicy)
+
+///
+/// Function Prototypes
+///
+/**
+ Execute Early-Post initialization of PFAT specific MSRs
+
+ @param[in] PeiServices - Indirect reference to the PEI Services Table.
+ @param[in] CpuPlatformPolicyPpi - Platform Policy PPI
+**/
+VOID
+PfatInit (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_CPU_PLATFORM_POLICY_PPI *CpuPlatformPolicyPpi
+ );
+
+#endif
diff --git a/ReferenceCode/Haswell/CpuS3/Pei/CpuAsm.asm b/ReferenceCode/Haswell/CpuS3/Pei/CpuAsm.asm
new file mode 100644
index 0000000..f396d99
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuS3/Pei/CpuAsm.asm
@@ -0,0 +1,147 @@
+;
+; 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
+; 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:
+;
+; CpuAsm.asm
+;
+; Abstract:
+;
+; This is the code that supports IA32 CPU architectural protocol
+;
+;------------------------------------------------------------------------------
+
+include MpEqu.inc
+
+.686p
+.model flat
+.code
+
+PAUSE32 MACRO
+ DB 0F3h
+ DB 090h
+ ENDM
+
+EnableMce proc near C public
+
+ mov eax, cr4
+ or eax, 40h
+ mov cr4, eax
+
+ ret
+
+EnableMce endp
+
+MpMtrrSynchUpEntry PROC NEAR C PUBLIC
+ ;
+ ; Enter no fill cache mode, CD=1(Bit30), NW=0 (Bit29)
+ ;
+ mov eax, cr0
+ and eax, 0DFFFFFFFh
+ or eax, 040000000h
+ mov cr0, eax
+ ;
+ ; Flush cache
+ ;
+ wbinvd
+ ;
+ ; Clear PGE flag Bit 7
+ ;
+ mov eax, cr4
+ mov edx, eax
+ and eax, 0FFFFFF7Fh
+ mov cr4, eax
+ ;
+ ; Flush all TLBs
+ ;
+ mov eax, cr3
+ mov cr3, eax
+
+ mov eax, edx
+
+ ret
+
+MpMtrrSynchUpEntry ENDP
+
+MpMtrrSynchUpExit PROC NEAR C PUBLIC
+
+ push ebp ; C prolog
+ mov ebp, esp
+ ;
+ ; Flush all TLBs the second time
+ ;
+ mov eax, cr3
+ mov cr3, eax
+ ;
+ ; Enable Normal Mode caching CD=NW=0, CD(Bit30), NW(Bit29)
+ ;
+ mov eax, cr0
+ and eax, 09FFFFFFFh
+ mov cr0, eax
+ ;
+ ; Set PGE Flag in CR4 if set
+ ;
+ mov eax, dword ptr [ebp + 8]
+ mov cr4, eax
+
+ pop ebp
+
+ ret
+
+MpMtrrSynchUpExit ENDP
+
+;-------------------------------------------------------------------------------
+; AsmAcquireMPLock (&Lock);
+;-------------------------------------------------------------------------------
+AsmAcquireMPLock PROC near C PUBLIC
+
+ pushad
+ mov ebp,esp
+
+ mov al, NotVacantFlag
+ mov ebx, dword ptr [ebp+24h]
+TryGetLock:
+ lock xchg al, byte ptr [ebx]
+ cmp al, VacantFlag
+ jz LockObtained
+
+ PAUSE32
+ jmp TryGetLock
+
+LockObtained:
+ popad
+ ret
+AsmAcquireMPLock ENDP
+
+;-------------------------------------------------------------------------------
+; AsmReleaseMPLock (&Lock);
+;-------------------------------------------------------------------------------------
+AsmReleaseMPLock PROC near C PUBLIC
+
+ pushad
+ mov ebp,esp
+
+ mov al, VacantFlag
+ mov ebx, dword ptr [ebp+24h]
+ lock xchg al, byte ptr [ebx]
+
+ popad
+ ret
+AsmReleaseMPLock ENDP
+
+END \ No newline at end of file
diff --git a/ReferenceCode/Haswell/CpuS3/Pei/CpuS3Peim.c b/ReferenceCode/Haswell/CpuS3/Pei/CpuS3Peim.c
new file mode 100644
index 0000000..ddf8ba1
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuS3/Pei/CpuS3Peim.c
@@ -0,0 +1,1035 @@
+/** @file
+ Cpu driver running on S3 boot path
+
+@copyright
+ Copyright (c) 2005 - 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
+
+**/
+
+///
+/// External include files do NOT need to be explicitly specified in real EDKII
+/// environment
+///
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGluePeim.h"
+#include "MpCommon.h"
+#include "BootGuardLibrary.h"
+#include EFI_PPI_DEFINITION (SmmAccess)
+#include EFI_PPI_DEPENDENCY (Stall)
+#include EFI_PPI_DEFINITION (CpuPlatformPolicy)
+
+#include EFI_GUID_DEFINITION (HOB)
+#include EFI_GUID_DEFINITION (StatusCodeDataTypeId)
+#include EFI_GUID_DEFINITION (SmramCpuDataHeader)
+#endif
+
+#define PEI_ACPI_CPU_DATA_HOB_GUID \
+ { 0x7682bbef, 0xb0b6, 0x4939, 0xae, 0x66, 0x1b, 0x3d, 0xf2, 0xf6, 0xaa, 0xf3};
+
+EFI_GUID gPeiAcpiCpuDataGuid = PEI_ACPI_CPU_DATA_HOB_GUID;
+typedef VOID (*S3_AP_PROCEDURE)(
+ MP_CPU_EXCHANGE_INFO *ExchangeInfo,
+ UINT64 *MtrrValues
+ );
+
+/**
+ This function handles SA S3 resume task
+
+ @param[in] PeiServices - Pointer to PEI Services Table.
+ @param[in] NotifyDesc - Pointer to the descriptor for the Notification event that
+ caused this function to execute.
+ @param[in] Ppi - Pointer to the PPI data associated with this function.
+
+ @retval EFI_STATUS - Always return EFI_SUCCESS
+**/
+static
+EFI_STATUS
+CpuS3ResumeAtEndOfPei (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
+ IN VOID *Ppi
+ );
+
+EFI_GUID gEfiPeiEndOfPeiPhasePpiGuid = EFI_PEI_END_OF_PEI_PHASE_PPI_GUID;
+STATIC EFI_PEI_NOTIFY_DESCRIPTOR mCpuS3ResumeNotifyDesc = {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiEndOfPeiPhasePpiGuid,
+ CpuS3ResumeAtEndOfPei
+};
+
+/**
+ Get APIC ID of processor
+
+ @retval APIC ID of processor
+**/
+UINT32
+GetApicID (
+ VOID
+ )
+{
+ EFI_CPUID_REGISTER CpuidRegisters;
+
+ AsmCpuid (
+ CPUID_VERSION_INFO,
+ &CpuidRegisters.RegEax,
+ &CpuidRegisters.RegEbx,
+ &CpuidRegisters.RegEcx,
+ &CpuidRegisters.RegEdx
+ );
+ return (UINT32) (CpuidRegisters.RegEbx >> 24);
+}
+
+/**
+ Send interrupt to CPU
+
+ @param[in] BroadcastMode - interrupt broadcast mode
+ @param[in] ApicID - APIC ID for sending interrupt
+ @param[in] VectorNumber - Vector number
+ @param[in] DeliveryMode - Interrupt delivery mode
+ @param[in] TriggerMode - Interrupt trigger mode
+ @param[in] Assert - Interrupt pin polarity
+ @param[in] PeiServices - Indirect reference to the PEI Services Table
+ @param[in] PeiStall - EFI_PEI_STALL_PPI to stall for some interval
+
+ @retval EFI_INVALID_PARAMETER - input parameter not correct
+ @retval EFI_NOT_READY - there was a pending interrupt
+ @retval EFI_SUCCESS - interrupt sent successfully
+**/
+EFI_STATUS
+SendInterrupt (
+ IN UINT32 BroadcastMode,
+ IN UINT32 ApicID,
+ IN UINT32 VectorNumber,
+ IN UINT32 DeliveryMode,
+ IN UINT32 TriggerMode,
+ IN BOOLEAN Assert,
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_STALL_PPI *PeiStall
+ )
+{
+ UINT64 ApicBaseReg;
+ EFI_PHYSICAL_ADDRESS ApicBase;
+ UINT32 ICRLow;
+ UINT32 ICRHigh;
+
+ ///
+ /// Initialze ICR high dword, since P6 family processor needs
+ /// the destination field to be 0x0F when it is a broadcast
+ ///
+ ICRHigh = 0x0f000000;
+ ICRLow = VectorNumber | (DeliveryMode << 8);
+
+ if (TriggerMode == TRIGGER_MODE_LEVEL) {
+ ICRLow |= 0x8000;
+ }
+
+ if (Assert) {
+ ICRLow |= 0x4000;
+ }
+
+ switch (BroadcastMode) {
+ case BROADCAST_MODE_SPECIFY_CPU:
+ ICRHigh = ApicID << 24;
+ break;
+
+ case BROADCAST_MODE_ALL_INCLUDING_SELF:
+ ICRLow |= 0x80000;
+ break;
+
+ case BROADCAST_MODE_ALL_EXCLUDING_SELF:
+ ICRLow |= 0xC0000;
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ApicBaseReg = AsmReadMsr64 (MSR_IA32_APIC_BASE);
+ ApicBase = ApicBaseReg & 0xffffff000ULL;
+
+ *(volatile UINT32 *) (UINTN) (ApicBase + APIC_REGISTER_ICR_HIGH_OFFSET) = ICRHigh;
+ *(volatile UINT32 *) (UINTN) (ApicBase + APIC_REGISTER_ICR_LOW_OFFSET) = ICRLow;
+
+ PeiStall->Stall (
+ PeiServices,
+ PeiStall,
+ 10 * STALL_ONE_MICRO_SECOND
+ );
+
+ ICRLow = *(volatile UINT32 *) (UINTN) (ApicBase + APIC_REGISTER_ICR_LOW_OFFSET);
+ if (ICRLow & 0x1000) {
+ return EFI_NOT_READY;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Programs XAPIC registers.
+
+ @param[in] BSP - Is this BSP?
+**/
+VOID
+ProgramXApic (
+ BOOLEAN BSP
+ )
+{
+ UINT64 ApicBaseReg;
+ EFI_PHYSICAL_ADDRESS ApicBase;
+ volatile UINT32 *EntryAddress;
+ UINT32 EntryValue;
+
+ ApicBaseReg = AsmReadMsr64 (MSR_IA32_APIC_BASE);
+ ApicBase = ApicBaseReg & 0xffffff000ULL;
+
+ ///
+ /// Program the Spurious Vectore entry
+ ///
+ EntryAddress = (UINT32 *) (UINTN) (ApicBase + APIC_REGISTER_SPURIOUS_VECTOR_OFFSET);
+ EntryValue = *EntryAddress;
+ EntryValue &= 0xFFFFFD0F;
+ EntryValue |= 0x10F;
+ *EntryAddress = EntryValue;
+
+ ///
+ /// Program the LINT1 vector entry as extINT
+ ///
+ EntryAddress = (UINT32 *) (UINTN) (ApicBase + APIC_REGISTER_LINT0_VECTOR_OFFSET);
+ EntryValue = *EntryAddress;
+
+ if (BSP) {
+ EntryValue &= 0xFFFE00FF;
+ EntryValue |= 0x700;
+ } else {
+ EntryValue |= 0x10000;
+ }
+
+ *EntryAddress = EntryValue;
+
+ ///
+ /// Program the LINT1 vector entry as NMI
+ ///
+ EntryAddress = (UINT32 *) (UINTN) (ApicBase + APIC_REGISTER_LINT1_VECTOR_OFFSET);
+ EntryValue = *EntryAddress;
+ EntryValue &= 0xFFFE00FF;
+ if (BSP) {
+ EntryValue |= 0x400;
+ } else {
+ EntryValue |= 0x10400;
+ }
+
+ *EntryAddress = EntryValue;
+
+}
+
+/**
+ Restore all MSR settings
+
+ @param[in] ScriptTable - contain the MSR settings that will be restored
+**/
+VOID
+InitializeFeatures (
+ IN MP_CPU_S3_SCRIPT_DATA *ScriptTable
+ )
+{
+ EFI_CPUID_REGISTER CpuidRegisters;
+ UINT32 ApicId;
+ UINT8 SkipMsr;
+ ///
+ /// Restore all the MSRs for processor
+ ///
+ AsmCpuid (
+ CPUID_VERSION_INFO,
+ &CpuidRegisters.RegEax,
+ &CpuidRegisters.RegEbx,
+ &CpuidRegisters.RegEcx,
+ &CpuidRegisters.RegEdx
+ );
+ ApicId = (CpuidRegisters.RegEbx >> 24);
+
+ while (ScriptTable->MsrIndex != 0) {
+ if (ApicId == ScriptTable->ApicId) {
+ SkipMsr = 0;
+ if ((ScriptTable->MsrIndex == MSR_PMG_CST_CONFIG) && (AsmReadMsr64 (MSR_PMG_CST_CONFIG) & B_CST_CONTROL_LOCK)) {
+ SkipMsr = 1;
+ }
+ if (SkipMsr == 0) {
+ AsmWriteMsr64 (ScriptTable->MsrIndex, ScriptTable->MsrValue);
+ }
+ }
+ ScriptTable++;
+ }
+}
+
+/**
+ Restore all MSR settings with debug message output
+
+ @param[in] PeiServices - General purpose services available to every PEIM.
+ @param[in] ScriptTable - Script table contain all MSR settings that will be restored
+**/
+VOID
+InitializeFeaturesLog (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN MP_CPU_S3_SCRIPT_DATA *ScriptTable
+ )
+{
+ EFI_CPUID_REGISTER CpuidRegisters;
+ UINT32 ApicId;
+ BOOLEAN SkipMsr;
+
+ ///
+ /// Restore all the MSRs for processor
+ ///
+ AsmCpuid (
+ CPUID_VERSION_INFO,
+ &CpuidRegisters.RegEax,
+ &CpuidRegisters.RegEbx,
+ &CpuidRegisters.RegEcx,
+ &CpuidRegisters.RegEdx
+ );
+ ApicId = (CpuidRegisters.RegEbx >> 24);
+
+ while (ScriptTable->MsrIndex != 0) {
+ if (ApicId == ScriptTable->ApicId) {
+ DEBUG ((EFI_D_INFO, "MSR Index - %x, MSR value - %x\n", ScriptTable->MsrIndex, ScriptTable->MsrValue));
+ SkipMsr = FALSE;
+ if ((ScriptTable->MsrIndex == MSR_PMG_CST_CONFIG) && (AsmReadMsr64 (MSR_PMG_CST_CONFIG) & B_CST_CONTROL_LOCK)) {
+ SkipMsr = TRUE;
+ }
+ if (ScriptTable->MsrIndex == MSR_IA32_DEBUG_INTERFACE) {
+ /* Access to MSR_IA32_DEBUG_INTERFACE is supported on
+ HSW B0, HSWULT B0 and CRW B0 Stepping
+ HSW stepping >= C0, HSWULT Stepping >= C0 and CRW stepping >= C0 stepping, if CPUID (EAX=1): ECX[11] = 1
+ */
+ switch (CpuidRegisters.RegEax) {
+ case (EnumCpuHsw + EnumHswA0):
+ DEBUG ((EFI_D_INFO,"MSR_IA32_DEBUG_INTERFACE is not supported on Ax CPU stepping\n"));
+ break;
+ case (EnumCpuHsw + EnumHswB0):
+ case (EnumCpuHswUlt + EnumHswUltB0):
+ case (EnumCpuCrw + EnumCrwB0):
+ if ((AsmReadMsr64 (MSR_IA32_DEBUG_INTERFACE) & B_DEBUG_INTERFACE_LOCK)) {
+ SkipMsr = TRUE;
+ }
+ break;
+ default:
+ if (CpuidRegisters.RegEcx & BIT11) {
+ if ((AsmReadMsr64 (MSR_IA32_DEBUG_INTERFACE) & B_DEBUG_INTERFACE_LOCK)) {
+ SkipMsr = TRUE;
+ }
+ }
+ break;
+ }
+ }
+ if (!SkipMsr) {
+ AsmWriteMsr64 (ScriptTable->MsrIndex, ScriptTable->MsrValue);
+ }
+ }
+ ScriptTable++;
+ }
+}
+
+/**
+ Initialize prefetcher settings
+
+ @param[in] MlcStreamerprefecterEnabled - Enable/Disable MLC streamer prefetcher
+ @param[in] MlcSpatialPrefetcherEnabled - Enable/Disable MLC spatial prefetcher
+**/
+VOID
+ProcessorsPrefetcherInitialization (
+ IN UINTN MlcStreamerprefecterEnabled,
+ IN UINTN MlcSpatialPrefetcherEnabled
+ )
+{
+ UINT64 MsrValue;
+ MsrValue = AsmReadMsr64 (MISC_FEATURE_CONTROL);
+
+ if (MlcStreamerprefecterEnabled == CPU_FEATURE_DISABLE) {
+ MsrValue |= B_MISC_FEATURE_CONTROL_MLC_STRP;
+ }
+
+ if (MlcSpatialPrefetcherEnabled == CPU_FEATURE_DISABLE) {
+ MsrValue |= B_MISC_FEATURE_CONTROL_MLC_SPAP;
+ }
+
+ if ((MsrValue & (B_MISC_FEATURE_CONTROL_MLC_STRP | B_MISC_FEATURE_CONTROL_MLC_SPAP)) != 0) {
+ AsmWriteMsr64 (MISC_FEATURE_CONTROL, MsrValue);
+ }
+
+ return;
+}
+
+/**
+ AP initialization
+
+ @param[in] ExchangeInfo - Pointer to the exchange info buffer for output.
+ @param[in] MtrrValues - buffer contains MTRR settings
+**/
+VOID
+MPRendezvousProcedure (
+ MP_CPU_EXCHANGE_INFO *ExchangeInfo,
+ UINT64 *MtrrValues
+ )
+{
+ UINT32 FailedRevision;
+ ACPI_CPU_DATA *AcpiCpuData;
+ EFI_PEI_SERVICES **PeiServices;
+ EFI_PEI_STALL_PPI *PeiStall;
+ MP_CPU_S3_DATA_POINTER *CpuS3DataPtr;
+
+ ///
+ /// Switch AP speed to BSP speed
+ ///
+ AsmWriteMsr64 (MSR_IA32_PERF_CTRL, ExchangeInfo->CpuPerfCtrlValue);
+
+ AcpiCpuData = (ACPI_CPU_DATA *) (ExchangeInfo->AcpiCpuDataAddress);
+ PeiServices = ExchangeInfo->PeiServices;
+ PeiStall = ExchangeInfo->PeiStall;
+
+ ProgramXApic (FALSE);
+
+ InitializeMicrocode (
+ ExchangeInfo,
+ (EFI_CPU_MICROCODE_HEADER **) (UINTN) ExchangeInfo->MicrocodePointer,
+ &FailedRevision
+ );
+
+ ProcessorsPrefetcherInitialization (
+ ExchangeInfo->CpuPlatformPolicyPpi->CpuConfig->MlcStreamerPrefetcher,
+ ExchangeInfo->CpuPlatformPolicyPpi->CpuConfig->MlcSpatialPrefetcher
+ );
+
+ ///
+ /// wait till all CPUs done the Microcode Load
+ ///
+ while (ExchangeInfo->McuLoadCount < AcpiCpuData->NumberOfCpus) {
+ CpuPause ();
+ }
+
+ MpMtrrSynchUp (MtrrValues);
+
+ InitializeFeatures (ExchangeInfo->S3BootScriptTable);
+
+ InterlockedIncrement (&(ExchangeInfo->FinishedCount));
+
+ ///
+ /// Sempahore check loop executed in memory
+ ///
+ (*ExchangeInfo->SemaphoreCheck)(&ExchangeInfo->FinishedCount);
+
+ InterlockedIncrement (&(ExchangeInfo->WakeupCount));
+
+ ///
+ /// Restore the MTRR programmed before OS boot
+ ///
+ /// MpMtrrSynchUp (MtrrValues);
+ ///
+ CpuS3DataPtr = (MP_CPU_S3_DATA_POINTER *) (UINTN) AcpiCpuData->CpuPrivateData;
+ SetMtrrRegisters (PeiServices, (EFI_MTRR_VALUES *) CpuS3DataPtr->S3BspMtrrTable);
+
+ while (ExchangeInfo->WakeupCount < AcpiCpuData->NumberOfCpus - 1) {
+ CpuPause ();
+ }
+
+ InterlockedIncrement (&(ExchangeInfo->FinishedCount));
+
+}
+
+/**
+ Wake up all the application processors
+
+ @param[in] PeiServices - Indirect reference to the PEI Services Table
+ @param[in] PeiStall - EFI_PEI_STALL_PPI to stall for some interval
+ @param[in] AcpiCpuData - pointer to ACPI_CPU_DATA structure
+ @param[in] MtrrValues - pointer to a buffer which stored MTRR settings
+
+ @retval EFI_SUCCESS - APs are successfully waked up
+**/
+EFI_STATUS
+WakeUpAPs (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_STALL_PPI *PeiStall,
+ ACPI_CPU_DATA *AcpiCpuData,
+ UINT64 *MtrrValues,
+ S3_AP_PROCEDURE Function
+ )
+{
+ EFI_PHYSICAL_ADDRESS WakeUpBuffer;
+ MP_CPU_EXCHANGE_INFO *ExchangeInfo;
+ MP_CPU_S3_DATA_POINTER *CpuS3DataPtr;
+ UINTN CpuPpiAddrDelta;
+ PEI_CPU_PLATFORM_POLICY_PPI *CpuPolicyPpi;
+
+ WakeUpBuffer = AcpiCpuData->WakeUpBuffer;
+ CopyMem ((VOID *) (UINTN) WakeUpBuffer, AsmGetAddressMap (), 0x1000 - 0x200);
+
+ ExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (WakeUpBuffer + (0x1000 - 0x200));
+
+ ExchangeInfo->Lock = 0;
+ ExchangeInfo->StackStart = (UINTN) AcpiCpuData->StackAddress;
+ ExchangeInfo->StackSize = STACK_SIZE_PER_PROC;
+ ExchangeInfo->ApFunction = (UINT32) Function;
+ ExchangeInfo->BufferStart = (UINT32) WakeUpBuffer;
+ ExchangeInfo->PmodeOffset = (UINT32) (AsmGetPmodeOffset ());
+ ExchangeInfo->SemaphoreCheck = (VOID (*)(UINT32 *))(AsmGetSemaphoreCheckOffset () + (UINT32) WakeUpBuffer);
+ ExchangeInfo->AcpiCpuDataAddress = (UINT32) AcpiCpuData;
+ ExchangeInfo->MtrrValuesAddress = (UINT32) MtrrValues;
+ ExchangeInfo->FinishedCount = (UINT32) 0;
+ ExchangeInfo->SerializeLock = (UINT32) 0;
+ ExchangeInfo->MicrocodePointer = (UINT32) (UINTN) AcpiCpuData->MicrocodePointerBuffer;
+ ExchangeInfo->StartState = (UINT32) 0;
+
+ CpuS3DataPtr = (MP_CPU_S3_DATA_POINTER *) (UINTN) AcpiCpuData->CpuPrivateData;
+ ExchangeInfo->S3BootScriptTable = (MP_CPU_S3_SCRIPT_DATA *) (UINTN) CpuS3DataPtr->S3BootScriptTable;
+ ExchangeInfo->VirtualWireMode = CpuS3DataPtr->VirtualWireMode;
+ ExchangeInfo->PeiServices = PeiServices;
+ ExchangeInfo->PeiStall = PeiStall;
+ ExchangeInfo->CpuPerfCtrlValue = AsmReadMsr64 (MSR_IA32_PERF_CTRL);
+
+ ExchangeInfo->CpuPlatformPolicyPpi = NULL;
+ PeiServicesLocatePpi (
+ &gPeiCpuPlatformPolicyPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &(ExchangeInfo->CpuPlatformPolicyPpi)
+ );
+
+ //
+ // Calculate delta from cache address to memory address
+ //
+ CpuPolicyPpi = ExchangeInfo->CpuPlatformPolicyPpi;
+ CpuPpiAddrDelta = CpuPolicyPpi->CpuPlatformPpiPtr - (UINTN)(CpuPolicyPpi);
+ //
+ // Calculate new address in memory for each pointer in PEI_CPU_PLATFORM_POLICY_PPI
+ //
+ CpuPolicyPpi->CpuConfig = (CPU_CONFIG_PPI *)((UINTN)CpuPolicyPpi->CpuConfig - CpuPpiAddrDelta);
+ CpuPolicyPpi->PowerMgmtConfig = (POWER_MGMT_CONFIG_PPI *)((UINTN)CpuPolicyPpi->PowerMgmtConfig - CpuPpiAddrDelta);
+ CpuPolicyPpi->SecurityConfig = (SECURITY_CONFIG_PPI *)((UINTN)CpuPolicyPpi->SecurityConfig - CpuPpiAddrDelta);
+ CpuPolicyPpi->SecurityConfig->PfatConfig = (PFAT_CONFIG *)((UINTN)CpuPolicyPpi->SecurityConfig->PfatConfig - CpuPpiAddrDelta);
+ CpuPolicyPpi->SecurityConfig->TxtConfig = (TXT_CONFIG *)((UINTN)CpuPolicyPpi->SecurityConfig->TxtConfig - CpuPpiAddrDelta);
+ CpuPolicyPpi->SecurityConfig->BootGuardConfig = (BOOT_GUARD_CONFIG *)((UINTN)CpuPolicyPpi->SecurityConfig->BootGuardConfig - CpuPpiAddrDelta);
+ CpuPolicyPpi->OverclockingConfig = (OVERCLOCKING_CONFIG_PPI *)((UINTN)CpuPolicyPpi->OverclockingConfig - CpuPpiAddrDelta);
+
+ CopyMem (
+ (VOID *) (UINTN) &ExchangeInfo->GdtrProfile,
+ (VOID *) (UINTN) AcpiCpuData->GdtrProfile,
+ sizeof (PSEUDO_DESCRIPTOR)
+ );
+ CopyMem (
+ (VOID *) (UINTN) &ExchangeInfo->IdtrProfile,
+ (VOID *) (UINTN) AcpiCpuData->IdtrProfile,
+ sizeof (PSEUDO_DESCRIPTOR)
+ );
+
+ DEBUG ((EFI_D_INFO, "Cpu S3 Bootscript at %08X\n", (UINT32) ExchangeInfo->S3BootScriptTable));
+
+#ifdef BOOT_GUARD_SUPPORT_FLAG
+#if BOOT_GUARD_SUPPORT_FLAG == 1
+ //
+ // Disable PBET before send IPI to APs
+ //
+ StopPbeTimer ();
+#endif
+#endif
+
+ ///
+ /// Don't touch MPCPU private data
+ /// Here we use ExchangeInfo instead
+ ///
+ ///
+ /// Send INIT IPI - SIPI to all APs
+ ///
+ SendInterrupt (
+ BROADCAST_MODE_ALL_EXCLUDING_SELF,
+ 0,
+ 0,
+ DELIVERY_MODE_INIT,
+ TRIGGER_MODE_EDGE,
+ TRUE,
+ PeiServices,
+ PeiStall
+ );
+
+ PeiStall->Stall (
+ PeiServices,
+ PeiStall,
+ 10 * STALL_ONE_MILLI_SECOND ///< 10ms
+ );
+
+ SendInterrupt (
+ BROADCAST_MODE_ALL_EXCLUDING_SELF,
+ 0,
+ (UINT32) RShiftU64 (WakeUpBuffer,
+ 12),
+ DELIVERY_MODE_SIPI,
+ TRIGGER_MODE_EDGE,
+ TRUE,
+ PeiServices,
+ PeiStall
+ );
+
+ PeiStall->Stall (
+ PeiServices,
+ PeiStall,
+ 200 * STALL_ONE_MICRO_SECOND ///< 200us
+ );
+
+ SendInterrupt (
+ BROADCAST_MODE_ALL_EXCLUDING_SELF,
+ 0,
+ (UINT32) RShiftU64 (WakeUpBuffer,
+ 12),
+ DELIVERY_MODE_SIPI,
+ TRIGGER_MODE_EDGE,
+ TRUE,
+ PeiServices,
+ PeiStall
+ );
+
+ PeiStall->Stall (
+ PeiServices,
+ PeiStall,
+ 200 * STALL_ONE_MICRO_SECOND ///< 200us
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This routine is used to search SMRAM and get SmramCpuData point.
+
+ @param[in] PeiServices - PEI services global pointer
+ @param[in] SmmAccessPpi - SmmAccess PPI instance
+
+ @retval SmramCpuData - The pointer of CPU information in SMRAM.
+**/
+STATIC
+SMRAM_CPU_DATA *
+GetSmmCpuData (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_SMM_ACCESS_PPI *SmmAccessPpi
+ )
+{
+ EFI_SMRAM_DESCRIPTOR *SmramRanges;
+ UINTN SmramRangeCount;
+ UINTN Size;
+ EFI_STATUS Status;
+ UINT32 Address;
+ SMRAM_CPU_DATA *SmramCpuData;
+
+ ///
+ /// Get all SMRAM range
+ ///
+ Size = 0;
+ Status = SmmAccessPpi->GetCapabilities (PeiServices, SmmAccessPpi, &Size, NULL);
+ ASSERT (Status == EFI_BUFFER_TOO_SMALL);
+
+ Status = PeiServicesAllocatePool (
+ Size,
+ (VOID **) &SmramRanges
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = SmmAccessPpi->GetCapabilities (PeiServices, SmmAccessPpi, &Size, SmramRanges);
+ ASSERT_EFI_ERROR (Status);
+
+ Size /= sizeof (*SmramRanges);
+ SmramRangeCount = Size;
+
+ ///
+ /// BUGBUG: We assume TSEG is the last range of SMRAM in SmramRanges
+ ///
+ SmramRanges += SmramRangeCount - 1;
+
+ DEBUG ((EFI_D_INFO, "TsegBase - %x\n", SmramRanges->CpuStart));
+ DEBUG ((EFI_D_INFO, "TsegTop - %x\n", SmramRanges->CpuStart + SmramRanges->PhysicalSize));
+
+ ///
+ /// Search SMRAM on page alignment for the SMMNVS signature
+ ///
+ for (Address = (UINT32) (SmramRanges->CpuStart + SmramRanges->PhysicalSize - EFI_PAGE_SIZE);
+ Address >= (UINT32) SmramRanges->CpuStart;
+ Address -= EFI_PAGE_SIZE
+ ) {
+ SmramCpuData = (SMRAM_CPU_DATA *) (UINTN) Address;
+ if (CompareGuid (&SmramCpuData->HeaderGuid, &gSmramCpuDataHeaderGuid)
+ && SmramCpuData->AcpiCpuData.NumberOfCpus == (UINT32)(AsmReadMsr64(0x35) & 0xffff)) { //(AMI_CHG)
+ ///
+ /// Find it
+ ///
+ return SmramCpuData;
+ }
+ }
+
+ ASSERT (FALSE);
+
+ return NULL;
+}
+
+/**
+ This routine is restore the CPU information from SMRAM to original reserved memory region.
+
+ @param[in] PeiServices - PEI services global pointer
+
+ @retval AcpiCpuData - The pointer of CPU information in reserved memory.
+**/
+ACPI_CPU_DATA *
+RestoreSmramCpuData (
+ IN EFI_PEI_SERVICES **PeiServices
+ )
+{
+ PEI_SMM_ACCESS_PPI *SmmAccessPpi;
+ SMRAM_CPU_DATA *SmramCpuData;
+ EFI_STATUS Status;
+ ACPI_CPU_DATA *AcpiCpuData;
+ MP_CPU_S3_DATA_POINTER *CpuS3DataPtr;
+ PSEUDO_DESCRIPTOR *Idtr;
+ PSEUDO_DESCRIPTOR *Gdtr;
+ UINTN MicrocodeSize;
+ EFI_CPU_MICROCODE_HEADER **Microcode;
+ EFI_CPU_MICROCODE_HEADER *LockBoxMicrocode;
+ UINTN Index;
+
+ Status = PeiServicesLocatePpi (
+ &gPeiSmmAccessPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &SmmAccessPpi
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Open all SMM regions
+ ///
+ Index = 0;
+ do {
+ Status = SmmAccessPpi->Open (PeiServices, SmmAccessPpi, Index);
+ Index++;
+ } while (!EFI_ERROR (Status));
+
+ SmramCpuData = GetSmmCpuData (PeiServices, SmmAccessPpi);
+ DEBUG ((EFI_D_INFO, "CpuS3 SmramCpuData - 0x%x \n", SmramCpuData));
+ DEBUG ((EFI_D_INFO, "SmramCpuData->GdtrProfileSize - %x\n", SmramCpuData->GdtrProfileSize));
+ DEBUG ((EFI_D_INFO, "SmramCpuData->GdtSize - %x\n", SmramCpuData->GdtSize));
+ DEBUG ((EFI_D_INFO, "SmramCpuData->IdtrProfileSize - %x\n", SmramCpuData->IdtrProfileSize));
+ DEBUG ((EFI_D_INFO, "SmramCpuData->IdtSize - %x\n", SmramCpuData->IdtSize));
+ DEBUG ((EFI_D_INFO, "SmramCpuData->CpuPrivateDataSize - %x\n", SmramCpuData->CpuPrivateDataSize));
+ DEBUG ((EFI_D_INFO, "SmramCpuData->S3BootScriptTableSize - %x\n", SmramCpuData->S3BootScriptTableSize));
+ DEBUG ((EFI_D_INFO, "SmramCpuData->S3BspMtrrTableSize - %x\n", SmramCpuData->S3BspMtrrTableSize));
+ DEBUG ((EFI_D_INFO, "SmramCpuData->MicrocodePointerBufferSize - %x\n", SmramCpuData->MicrocodePointerBufferSize));
+ DEBUG ((EFI_D_INFO, "SmramCpuData->MicrocodeDataBufferSize - %x\n", SmramCpuData->MicrocodeDataBufferSize));
+ DEBUG ((EFI_D_INFO, "SmramCpuData->GdtrProfileOffset - %x\n", SmramCpuData->GdtrProfileOffset));
+ DEBUG ((EFI_D_INFO, "SmramCpuData->GdtOffset - %x\n", SmramCpuData->GdtOffset));
+ DEBUG ((EFI_D_INFO, "SmramCpuData->IdtrProfileOffset - %x\n", SmramCpuData->IdtrProfileOffset));
+ DEBUG ((EFI_D_INFO, "SmramCpuData->IdtOffset - %x\n", SmramCpuData->IdtOffset));
+ DEBUG ((EFI_D_INFO, "SmramCpuData->CpuPrivateDataOffset - %x\n", SmramCpuData->CpuPrivateDataOffset));
+ DEBUG ((EFI_D_INFO, "SmramCpuData->S3BootScriptTableOffset - %x\n", SmramCpuData->S3BootScriptTableOffset));
+ DEBUG ((EFI_D_INFO, "SmramCpuData->S3BspMtrrTableOffset - %x\n", SmramCpuData->S3BspMtrrTableOffset));
+ DEBUG ((EFI_D_INFO, "SmramCpuData->MicrocodePointerBufferOffset - %x\n", SmramCpuData->MicrocodePointerBufferOffset));
+ DEBUG ((EFI_D_INFO, "SmramCpuData->MicrocodeDataBufferOffset - %x\n", SmramCpuData->MicrocodeDataBufferOffset));
+
+ ///
+ /// Start restore data to NVS
+ ///
+ AcpiCpuData = (ACPI_CPU_DATA *) (UINTN) SmramCpuData->AcpiCpuPointer;
+ CopyMem (AcpiCpuData, &SmramCpuData->AcpiCpuData, sizeof (ACPI_CPU_DATA));
+
+ CopyMem (
+ (VOID *) (UINTN) AcpiCpuData->GdtrProfile,
+ (UINT8 *) SmramCpuData + SmramCpuData->GdtrProfileOffset,
+ SmramCpuData->GdtrProfileSize
+ );
+ Gdtr = (PSEUDO_DESCRIPTOR *) (UINTN) AcpiCpuData->GdtrProfile;
+ CopyMem (
+ (VOID *) (UINTN) Gdtr->Base,
+ (UINT8 *) SmramCpuData + SmramCpuData->GdtOffset,
+ SmramCpuData->GdtSize
+ );
+ CopyMem (
+ (VOID *) (UINTN) AcpiCpuData->IdtrProfile,
+ (UINT8 *) SmramCpuData + SmramCpuData->IdtrProfileOffset,
+ SmramCpuData->IdtrProfileSize
+ );
+ Idtr = (PSEUDO_DESCRIPTOR *) (UINTN) AcpiCpuData->IdtrProfile;
+ CopyMem (
+ (VOID *) (UINTN) Idtr->Base,
+ (UINT8 *) SmramCpuData + SmramCpuData->IdtOffset,
+ SmramCpuData->IdtSize
+ );
+
+ CopyMem (
+ (VOID *) (UINTN) AcpiCpuData->CpuPrivateData,
+ (UINT8 *) SmramCpuData + SmramCpuData->CpuPrivateDataOffset,
+ SmramCpuData->CpuPrivateDataSize
+ );
+ CpuS3DataPtr = (MP_CPU_S3_DATA_POINTER *) (UINTN) AcpiCpuData->CpuPrivateData;
+ CopyMem (
+ (VOID *) (UINTN) CpuS3DataPtr->S3BootScriptTable,
+ (UINT8 *) SmramCpuData + SmramCpuData->S3BootScriptTableOffset,
+ SmramCpuData->S3BootScriptTableSize
+ );
+ CopyMem (
+ (VOID *) (UINTN) CpuS3DataPtr->S3BspMtrrTable,
+ (UINT8 *) SmramCpuData + SmramCpuData->S3BspMtrrTableOffset,
+ SmramCpuData->S3BspMtrrTableSize
+ );
+
+ CopyMem (
+ (VOID *) (UINTN) AcpiCpuData->MicrocodePointerBuffer,
+ (UINT8 *) SmramCpuData + SmramCpuData->MicrocodePointerBufferOffset,
+ SmramCpuData->MicrocodePointerBufferSize
+ );
+ ///
+ /// Restore Microcode Data
+ ///
+ Microcode = (VOID *) (UINTN) AcpiCpuData->MicrocodePointerBuffer;
+ LockBoxMicrocode = (EFI_CPU_MICROCODE_HEADER *) ((UINT8 *) SmramCpuData + SmramCpuData->MicrocodeDataBufferOffset);
+ if (Microcode != NULL) {
+ Index = 0;
+ MicrocodeSize = 0;
+ while (Microcode[Index] != NULL) {
+ if (LockBoxMicrocode->DataSize == 0) {
+ MicrocodeSize = 2048;
+ } else {
+ MicrocodeSize = LockBoxMicrocode->TotalSize;
+ }
+
+ CopyMem (Microcode[Index], LockBoxMicrocode, MicrocodeSize);
+ LockBoxMicrocode = (EFI_CPU_MICROCODE_HEADER *) ((UINT8 *) LockBoxMicrocode + MicrocodeSize);
+ Index++;
+ }
+ }
+ ///
+ /// Close all SMM regions
+ ///
+ Index = 0;
+ do {
+ Status = SmmAccessPpi->Close (PeiServices, SmmAccessPpi, Index);
+ Index++;
+ } while (!EFI_ERROR (Status));
+
+ return AcpiCpuData;
+}
+
+/**
+ Initialize multiple processors.
+
+ @param[in] FfsHeader - Pointer to an alleged FFS file.
+ @param[in] PeiServices - Indirect reference to the PEI Services Table
+
+ @retval EFI_SUCCESS - Multiple processors are intialized successfully
+**/
+EFI_STATUS
+InitializeCpu (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_STALL_PPI *PeiStall;
+ ACPI_CPU_DATA *AcpiCpuData;
+ EFI_BOOT_MODE BootMode;
+ UINT64 *MtrrValues;
+ MP_CPU_S3_DATA_POINTER *CpuS3DataPtr;
+ UINTN VariableMtrrNumber;
+ EFI_PHYSICAL_ADDRESS WakeUpBuffer;
+ MP_CPU_EXCHANGE_INFO *ExchangeInfo;
+ UINT32 FailedRevision;
+ VOID *Hob;
+
+ DEBUG ((EFI_D_INFO, "Cpu S3 dispatch\n"));
+
+ Status = PeiServicesGetBootMode (&BootMode);
+ if (EFI_ERROR (Status)) {
+ ///
+ /// If not in S3 boot path. do nothing
+ ///
+ return EFI_SUCCESS;
+ }
+
+ if (BootMode != BOOT_ON_S3_RESUME) {
+ return EFI_SUCCESS;
+ }
+
+ DEBUG ((EFI_D_INFO, "Cpu S3 Entrypoint\n"));
+
+ ///
+ /// Restore ACPI Nvs data from SMRAM
+ ///
+ AcpiCpuData = RestoreSmramCpuData (PeiServices);
+ DEBUG ((EFI_D_INFO, "CpuS3 RestoreSmramCpuData - 0x%x \n", AcpiCpuData));
+
+ AcpiCpuData->S3BootPath = TRUE;
+
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiStallPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &PeiStall
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ CpuS3DataPtr = (MP_CPU_S3_DATA_POINTER *) (UINTN) AcpiCpuData->CpuPrivateData;
+
+ VariableMtrrNumber = (UINTN) ((UINT64) AsmReadMsr64 (IA32_MTRR_CAP) & B_IA32_MTRR_VARIABLE_SUPPORT) * 2;
+ Status = PeiServicesAllocatePool (
+ (FixedMtrrNumber + MtrrDefTypeNumber + VariableMtrrNumber) * sizeof (UINT64),
+ (VOID **) &MtrrValues
+ );
+ ASSERT_EFI_ERROR (Status);
+ ReadMtrrRegisters (PeiServices, MtrrValues);
+
+ WakeUpBuffer = AcpiCpuData->WakeUpBuffer;
+ ExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (WakeUpBuffer + (0x1000 - 0x200));
+ ExchangeInfo->WakeupCount = (UINT32) 0;
+ ExchangeInfo->FinishedCount = (UINT32) 0;
+
+ ///
+ /// Restore AP configuration
+ ///
+ WakeUpAPs (PeiServices, PeiStall, AcpiCpuData, MtrrValues, MPRendezvousProcedure);
+
+ ///
+ /// Program XApic register
+ ///
+ ProgramXApic (
+ TRUE
+ );
+
+ InitializeMicrocode (
+ ExchangeInfo,
+ (EFI_CPU_MICROCODE_HEADER **) (UINTN) AcpiCpuData->MicrocodePointerBuffer,
+ &FailedRevision
+ );
+
+ ///
+ /// Restore features for BSP
+ ///
+ InitializeFeaturesLog (
+ PeiServices,
+ (MP_CPU_S3_SCRIPT_DATA *) CpuS3DataPtr->S3BootScriptTable
+ );
+
+ ///
+ /// Save acpi cpu data into one hob, it will be used by a callback when End of Pei Signal installed.
+ ///
+ Hob = BuildGuidDataHob (
+ &gPeiAcpiCpuDataGuid,
+ (VOID *)(UINTN)AcpiCpuData,
+ (UINTN) sizeof (ACPI_CPU_DATA)
+ );
+ ASSERT (Hob != NULL);
+
+ //(AMI_CHG)>
+ //DEBUG ((EFI_D_INFO, "Install CPU S3 Notify callback\n"));
+ //Status = PeiServicesNotifyPpi (&mCpuS3ResumeNotifyDesc);
+ //ASSERT_EFI_ERROR (Status);
+ //(AMI_CHG)<
+
+ ///
+ /// Wait for all APs to complete
+ ///
+ while (ExchangeInfo->FinishedCount < AcpiCpuData->NumberOfCpus - 1) {
+ CpuPause ();
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function handles CPU S3 resume task
+
+ @param[in] PeiServices - Pointer to PEI Services Table.
+ @param[in] NotifyDesc - Pointer to the descriptor for the Notification event that
+ caused this function to execute.
+ @param[in] Ppi - Pointer to the PPI data associated with this function.
+
+ @retval EFI_STATUS - Always return EFI_SUCCESS
+**/
+STATIC
+EFI_STATUS
+CpuS3ResumeAtEndOfPei (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
+ IN VOID *Ppi
+ )
+{
+
+ EFI_STATUS Status;
+ EFI_PEI_STALL_PPI *PeiStall;
+ ACPI_CPU_DATA *AcpiCpuData;
+ EFI_PHYSICAL_ADDRESS WakeUpBuffer;
+ MP_CPU_S3_DATA_POINTER *CpuS3DataPtr;
+ MP_CPU_EXCHANGE_INFO *ExchangeInfo;
+ VOID *Hob;
+
+ DEBUG ((EFI_D_INFO, "Cpu S3 callback Entry\n"));
+
+ ///
+ /// Find the saved acpi cpu data from HOB.
+ ///
+ AcpiCpuData = NULL;
+ Hob = GetFirstGuidHob (&gPeiAcpiCpuDataGuid);
+ if (Hob != NULL) {
+ AcpiCpuData = (ACPI_CPU_DATA *) ((UINTN) Hob + sizeof (EFI_HOB_GUID_TYPE));
+ ASSERT (AcpiCpuData != NULL);
+ if (AcpiCpuData == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+ WakeUpBuffer = AcpiCpuData->WakeUpBuffer;
+ ExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (WakeUpBuffer + (0x1000 - 0x200));
+ ///
+ /// Have APs to continue the task - Restore S3BspMtrrTable
+ ///
+ ExchangeInfo->WakeupCount = (UINT32) 0;
+ ExchangeInfo->FinishedCount = (UINT32) 0;
+
+ PeiStall = NULL;
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiStallPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &PeiStall
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Set MTRR to the final values
+ /// Do not do it too early so as to avoid performance penalty
+ ///
+ CpuS3DataPtr = (MP_CPU_S3_DATA_POINTER *) (UINTN) AcpiCpuData->CpuPrivateData;
+
+#ifdef EFI_DEBUG
+ ShowMtrrRegisters (PeiServices, (EFI_MTRR_VALUES *) CpuS3DataPtr->S3BspMtrrTable);
+#endif
+ SetMtrrRegisters (PeiServices, (EFI_MTRR_VALUES *) CpuS3DataPtr->S3BspMtrrTable);
+
+ PeiStall->Stall (
+ PeiServices,
+ PeiStall,
+ 1 * STALL_ONE_MILLI_SECOND ///< 1ms
+ );
+
+ while (ExchangeInfo->FinishedCount < AcpiCpuData->NumberOfCpus - 1) {
+ CpuPause ();
+ }
+
+ return EFI_SUCCESS;
+
+}
diff --git a/ReferenceCode/Haswell/CpuS3/Pei/CpuS3Peim.cif b/ReferenceCode/Haswell/CpuS3/Pei/CpuS3Peim.cif
new file mode 100644
index 0000000..2cdadb9
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuS3/Pei/CpuS3Peim.cif
@@ -0,0 +1,18 @@
+<component>
+ name = "CpuS3Peim"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\CpuS3\Pei"
+ RefName = "CpuS3Peim"
+[files]
+"CpuAsm.asm"
+"CpuS3Peim.c"
+"CpuS3Peim.dxs"
+"CpuS3Peim.inf"
+"CpuS3Peim.mak"
+"CpuS3Peim.sdl"
+"Microcode.c"
+"MpCommon.h"
+"MtrrSync.c"
+"MpFuncs.asm"
+"MpEqu.inc"
+<endComponent>
diff --git a/ReferenceCode/Haswell/CpuS3/Pei/CpuS3Peim.dxs b/ReferenceCode/Haswell/CpuS3/Pei/CpuS3Peim.dxs
new file mode 100644
index 0000000..45d6061
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuS3/Pei/CpuS3Peim.dxs
@@ -0,0 +1,31 @@
+/** @file
+ Dependency expression source file.
+
+@copyright
+ Copyright (c) 2005 - 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 "EfiDepex.h"
+#include EFI_PPI_DEFINITION (BootMode)
+#include EFI_PPI_CONSUMER (MemoryDiscovered)
+#include EFI_PPI_DEFINITION (SmmAccess)
+
+DEPENDENCY_START
+ PEI_MASTER_BOOT_MODE_PEIM_PPI AND
+ PEI_PERMANENT_MEMORY_INSTALLED_PPI_GUID AND
+ PEI_SMM_ACCESS_PPI_GUID
+DEPENDENCY_END
diff --git a/ReferenceCode/Haswell/CpuS3/Pei/CpuS3Peim.inf b/ReferenceCode/Haswell/CpuS3/Pei/CpuS3Peim.inf
new file mode 100644
index 0000000..bb2c9c0
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuS3/Pei/CpuS3Peim.inf
@@ -0,0 +1,102 @@
+## @file
+# @todo ADD DESCRIPTION
+#
+#@copyright
+# Copyright (c) 2005 - 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
+#
+
+[defines]
+BASE_NAME = CpuS3Peim
+FILE_GUID = C866BD71-7C79-4BF1-A93B-066B830D8F9A
+COMPONENT_TYPE = PE32_PEIM
+
+[sources.common]
+ CpuS3Peim.c
+ MtrrSync.c
+ Microcode.c
+
+ MpFuncs.asm
+ CpuAsm.asm
+
+#
+# Edk II Glue Driver Entry Point
+#
+ EdkIIGluePeimEntryPoint.c
+
+[includes.common]
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Pei/Include
+ $(EDK_SOURCE)/Foundation/Cpu/Pentium/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include/Library
+
+#
+# Edk II Glue Library, some hearder are included by R9 header so have to include
+#
+ $(EFI_SOURCE)
+ $(EFI_SOURCE)/Framework
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include/Library
+ $(EFI_SOURCE)/$(PROJECT_SA_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_SA_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_SA_ROOT)/SampleCode
+
+
+[libraries.common]
+ EdkFrameworkPpiLib
+ EdkIIGlueBaseLib
+ EdkIIGlueBaseMemoryLib
+ EdkIIGluePeiDebugLibReportStatusCode
+ EdkIIGluePeiReportStatusCodeLib
+ EdkIIGluePeiServicesLib
+ EdkPpiLib
+ CpuPpiLib
+ $(PROJECT_SA_FAMILY)SampleCodePpiLib
+ CpuGuidLib
+ CpuIA32Lib
+ EdkIIGlueBaseTimerLibLocalApic
+ EdkIIGluePeiHobLib
+ CpuPlatformLib
+ BootGuardLib
+
+[nmake.common]
+ IMAGE_ENTRY_POINT=_ModuleEntryPoint
+ DPX_SOURCE=CpuS3Peim.dxs
+
+#
+# Module Entry Point
+#
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=InitializeCpu
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_BASE_LIB__ \
+ -D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ -D __EDKII_GLUE_PEI_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ -D __EDKII_GLUE_PEI_REPORT_STATUS_CODE_LIB__ \
+ -D __EDKII_GLUE_PEI_SERVICES_LIB__
diff --git a/ReferenceCode/Haswell/CpuS3/Pei/CpuS3Peim.mak b/ReferenceCode/Haswell/CpuS3/Pei/CpuS3Peim.mak
new file mode 100644
index 0000000..1fe6836
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuS3/Pei/CpuS3Peim.mak
@@ -0,0 +1,76 @@
+# MAK file for the eModule: CpuS3Peim
+
+EDK : CpuS3Peim
+
+BUILD_CpuS3Peim_DIR = $(BUILD_DIR)\$(CpuS3Peim_DIR)
+
+$(BUILD_DIR)\CpuS3Peim.mak : $(CpuS3Peim_DIR)\CpuS3Peim.cif $(BUILD_RULES)
+ $(CIF2MAK) $(CpuS3Peim_DIR)\CpuS3Peim.cif $(CIF2MAK_DEFAULTS)
+
+CpuS3Peim : $(BUILD_DIR)\CpuS3Peim.MAK CpuS3PeimBin
+
+CpuS3Peim_OBJECTS = \
+ $(BUILD_CpuS3Peim_DIR)\CpuS3Peim.obj \
+ $(BUILD_CpuS3Peim_DIR)\MtrrSync.obj \
+ $(BUILD_CpuS3Peim_DIR)\Microcode.obj \
+ $(BUILD_CpuS3Peim_DIR)\MpFuncs.obj \
+ $(BUILD_CpuS3Peim_DIR)\CpuAsm.obj
+
+CpuS3Peim_MY_INCLUDES= \
+ $(EDK_INCLUDES) \
+ /I$(PROJECT_CPU_ROOT) \
+ /I$(PROJECT_CPU_ROOT)\Include \
+ $(PROJECT_CPU_INCLUDES)\
+ /I$(INTEL_SYSTEM_AGENT_DIR) \
+ /I$(INTEL_SYSTEM_AGENT_DIR)\Include \
+ /I$(INTEL_SYSTEM_AGENT_DIR)\SampleCode \
+
+#- $(CPU_INCLUDES)\
+
+CpuS3Peim_DEFINES = $(MY_DEFINES)\
+ /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=InitializeCpu"\
+ /D __EDKII_GLUE_BASE_LIB__ \
+ /D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ /D __EDKII_GLUE_PEI_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ /D __EDKII_GLUE_PEI_REPORT_STATUS_CODE_LIB__ \
+ /D __EDKII_GLUE_PEI_SERVICES_LIB__ \
+ /D __EDKII_GLUE_PEI_SERVICES_TABLE_POINTER_LIB_MM7__ \
+
+
+CpuS3Peim_LIBS =\
+ $(EDKFRAMEWORKPPILIB)\
+ $(EdkIIGlueBaseLib_LIB)\
+ $(EdkIIGlueBaseMemoryLib_LIB) \
+ $(EdkIIGluePeiDebugLibReportStatusCode_LIB) \
+ $(EdkIIGluePeiReportStatusCodeLib_LIB)\
+ $(EdkIIGluePeiServicesLib_LIB)\
+ $(EDKPPILIB)\
+ $(EdkIIGlueBaseTimerLibLocalApic_LIB)\
+ $(EdkIIGluePeiHobLib_LIB) \
+ $(CPU_PPI_LIB)\
+ $(INTEL_SA_PPI_LIB)\
+ $(CpuGuidLib_LIB)\
+ $(CPUIA32LIB)\
+ $(EdkIIGlueBasePciLibPciExpress_LIB)\
+ $(EdkIIGlueBasePciExpressLib_LIB)\
+ $(PchPlatformPeiLib_LIB)\
+ $(CpuPlatformLib_LIB)\
+ $(BootGuardLib_LIB)\
+ $(IntelSaSampleCodePpiLib_LIB)\
+
+CpuS3PeimBin : $(CpuS3Peim_LIBS)
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\CpuS3Peim.mak all\
+ NAME=CpuS3Peim\
+ MAKEFILE=$(BUILD_DIR)\CpuS3Peim.mak \
+ "MY_INCLUDES=$(CpuS3Peim_MY_INCLUDES)" \
+ "MY_DEFINES=$(CpuS3Peim_DEFINES)"\
+ OBJECTS="$(CpuS3Peim_OBJECTS)" \
+ GUID=C866BD71-7C79-4BF1-A93B-066B830D8F9A\
+ ENTRY_POINT=_ModuleEntryPoint \
+ TYPE=PEIM \
+ EDKIIModule=PEIM\
+ DEPEX1=$(CpuS3Peim_DIR)\CpuS3Peim.DXS \
+ DEPEX1_TYPE=EFI_SECTION_PEI_DEPEX \
+ COMPRESS=0
+#-----------------------------------------------------------------------
diff --git a/ReferenceCode/Haswell/CpuS3/Pei/CpuS3Peim.sdl b/ReferenceCode/Haswell/CpuS3/Pei/CpuS3Peim.sdl
new file mode 100644
index 0000000..011eee3
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuS3/Pei/CpuS3Peim.sdl
@@ -0,0 +1,37 @@
+TOKEN
+ Name = "CpuS3Peim_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable Cpu Pei init support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+End
+
+PATH
+ Name = "CpuS3Peim_DIR"
+End
+
+MODULE
+ Help = "Includes CpuS3Peim.mak to Project"
+ File = "CpuS3Peim.mak"
+End
+
+#-ELINK
+#- Name = "CpuS3Peim_INCLUDES"
+#- InvokeOrder = ReplaceParent
+#-End
+#-
+#-ELINK
+#- Name = "/I$(CpuS3Peim_DIR)"
+#- Parent = "CpuS3Peim_INCLUDES"
+#- InvokeOrder = AfterParent
+#-End
+
+ELINK
+ Name = "$(BUILD_DIR)\CpuS3Peim.ffs"
+ Parent = "FV_BB"
+ InvokeOrder = AfterParent
+End
+
diff --git a/ReferenceCode/Haswell/CpuS3/Pei/Microcode.c b/ReferenceCode/Haswell/CpuS3/Pei/Microcode.c
new file mode 100644
index 0000000..4d596d3
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuS3/Pei/Microcode.c
@@ -0,0 +1,472 @@
+/** @file
+ CPU microcode update PEIM
+
+@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
+
+**/
+
+///
+/// External include files do NOT need to be explicitly specified in real EDKII
+/// environment
+///
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGluePeim.h"
+#include "MpCommon.h"
+#define SKIP_MICROCODE_CHECKSUM_CHECK 1
+#endif
+///
+/// Array of pointers which each points to 1 microcode update binary (in memory)
+///
+EFI_CPU_MICROCODE_HEADER **mMicrocodePointerBuffer;
+
+///
+/// Function declarations
+///
+EFI_STATUS
+FindLoadMicrocode (
+ IN UINT32 Cpuid,
+ IN EFI_CPU_MICROCODE_HEADER **MicrocodePointerBuffer,
+ IN OUT UINT32 *Revision
+ );
+
+/**
+ Check number of cores in the package.
+
+ @retval Number of cores in the package.
+**/
+UINT8
+GetCoreNumber (
+ VOID
+ )
+{
+ EFI_CPUID_REGISTER Cpuid;
+ AsmCpuidEx (
+ 4,
+ 0,
+ &Cpuid.RegEax,
+ NULL,
+ NULL,
+ NULL
+ );
+ return (UINT8) ((RShiftU64 (Cpuid.RegEax, 26) & 0x3f) + 1);
+}
+
+/**
+ Check if this is non-core processor - HT AP thread
+
+ @retval TRUE if this is HT AP thread
+ @retval FALSE if this is core thread
+**/
+BOOLEAN
+IsSecondaryThread (
+ VOID
+ )
+{
+ UINT32 ApicID;
+ EFI_CPUID_REGISTER CpuidRegisters;
+ UINT8 CpuCount;
+ UINT8 CoreCount;
+ UINT8 CpuPerCore;
+ UINT32 Mask;
+
+ ApicID = GetApicID ();
+
+ AsmCpuid (
+ CPUID_VERSION_INFO,
+ &CpuidRegisters.RegEax,
+ &CpuidRegisters.RegEbx,
+ &CpuidRegisters.RegEcx,
+ &CpuidRegisters.RegEdx
+ );
+ if ((CpuidRegisters.RegEdx & 0x10000000) == 0) {
+ return FALSE;
+ }
+
+ CpuCount = (UINT8) ((CpuidRegisters.RegEbx >> 16) & 0xff);
+ if (CpuCount == 1) {
+ return FALSE;
+ }
+
+ AsmCpuid (
+ CPUID_SIGNATURE,
+ &CpuidRegisters.RegEax,
+ &CpuidRegisters.RegEbx,
+ &CpuidRegisters.RegEcx,
+ &CpuidRegisters.RegEdx
+ );
+ if (CpuidRegisters.RegEax > 3) {
+
+ CoreCount = GetCoreNumber ();
+ } else {
+ CoreCount = 1;
+ }
+ ///
+ /// Assumes there is symmetry across core boundary, i.e. each core within a package has the same number of logical processors
+ ///
+ if (CpuCount == CoreCount) {
+ return FALSE;
+ }
+
+ CpuPerCore = CpuCount / CoreCount;
+
+ ///
+ /// Assume 1 Core has no more than 8 threads
+ ///
+ if (CpuPerCore == 2) {
+ Mask = 0x1;
+ } else if (CpuPerCore <= 4) {
+ Mask = 0x3;
+ } else {
+ Mask = 0x7;
+ }
+
+ if ((ApicID & Mask) == 0) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+/**
+ Returns the processor microcode revision of the processor installed in the system.
+
+ @retval Processor Microcode Revision
+**/
+UINT32
+GetCpuUcodeRevision (
+ VOID
+ )
+{
+ AsmWriteMsr64 (MSR_IA32_BIOS_SIGN_ID, 0);
+ EfiCpuid (CPUID_VERSION_INFO, NULL);
+ return (UINT32) RShiftU64 (AsmReadMsr64 (MSR_IA32_BIOS_SIGN_ID), 32);
+}
+
+/**
+ Wait till all primary threads done the microcode load
+
+ @param[in] ExchangeInfo - Pointer to the exchange info buffer for output.
+**/
+VOID
+WaitForPrimaryThreadMcuUpdate (
+ IN MP_CPU_EXCHANGE_INFO *ExchangeInfo
+ )
+{
+ UINTN CoreNumber;
+ CoreNumber = (UINTN) ((RShiftU64 (AsmReadMsr64 (MSR_CORE_THREAD_COUNT), 16)) & 0xffff);
+ if (IsSecondaryThread ()) {
+ while (ExchangeInfo->McuLoadCount < CoreNumber) {
+ CpuPause ();
+ }
+ }
+}
+
+/**
+ This function checks the MCU revision to decide if BIOS needs to load
+ microcode.
+
+ @param[in] MicrocodePointer - Microcode in memory
+ @param[in] Revision - Current CPU microcode revision
+
+ @retval EFI_SUCCESS - BIOS needs to load microcode
+ @retval EFI_ABORTED - Don't need to update microcode
+**/
+EFI_STATUS
+CheckMcuRevision (
+ IN EFI_CPU_MICROCODE_HEADER *MicrocodePointer,
+ IN UINT32 Revision
+ )
+{
+ EFI_STATUS Status;
+ Status = EFI_ABORTED;
+
+ if (Revision == 0) {
+ Status = EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+/**
+ This will locate a processor microcode and if it finds a newer revision, it will
+ load it to the processor.
+
+ @param[in] ExchangeInfo - Pointer to the exchange info buffer for output.
+ @param[in] MicrocodePointerBuffer - The Array of pointers which each points to 1 microcode update binary (in memory)
+ @param[in] FailedRevision - The microcode revision that fails to be loaded
+
+ @retval EFI_SUCCESS - A new microcode update is loaded
+ @retval Other - Due to some reason, no new microcode update is loaded
+**/
+EFI_STATUS
+InitializeMicrocode (
+ IN MP_CPU_EXCHANGE_INFO *ExchangeInfo,
+ IN EFI_CPU_MICROCODE_HEADER **MicrocodePointerBuffer,
+ OUT UINT32 *FailedRevision
+ )
+{
+ EFI_STATUS Status;
+ EFI_CPUID_REGISTER Cpuid;
+ UINT32 UcodeRevision;
+ ACPI_CPU_DATA *mAcpiCpuData;
+
+ mAcpiCpuData = (ACPI_CPU_DATA *) (ExchangeInfo->AcpiCpuDataAddress);
+
+ AsmCpuid (
+ CPUID_VERSION_INFO,
+ &Cpuid.RegEax,
+ &Cpuid.RegEbx,
+ &Cpuid.RegEcx,
+ &Cpuid.RegEdx
+ );
+
+ WaitForPrimaryThreadMcuUpdate (ExchangeInfo);
+ UcodeRevision = GetCpuUcodeRevision ();
+ Status = FindLoadMicrocode (
+ Cpuid.RegEax,
+ MicrocodePointerBuffer,
+ &UcodeRevision
+ );
+ *FailedRevision = UcodeRevision;
+
+ InterlockedIncrement (&(ExchangeInfo->McuLoadCount));
+ return Status;
+}
+
+/**
+ This will load the microcode to the processors.
+
+ @param[in] MicrocodeEntryPoint - The microcode update pointer
+ @param[in] Revision - The current (before load this microcode update) microcode revision
+
+ @retval EFI_SUCCESS - Microcode loaded
+ @retval EFI_LOAD_ERROR - Microcode not loaded
+**/
+EFI_STATUS
+LoadMicrocode (
+ IN EFI_CPU_MICROCODE_HEADER *MicrocodeEntryPoint,
+ IN UINT32 *Revision
+ )
+{
+ ///
+ /// Load the Processor Microcode
+ ///
+ AsmWriteMsr64 (
+ MSR_IA32_BIOS_UPDT_TRIG,
+ (UINT64) ((UINTN) MicrocodeEntryPoint + sizeof (EFI_CPU_MICROCODE_HEADER))
+ );
+
+ ///
+ /// Verify that the microcode has been loaded
+ ///
+ if (GetCpuUcodeRevision () == *Revision) {
+ return EFI_LOAD_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Verify the DWORD type checksum
+
+ @param[in] ChecksumAddr - The start address to be checkumed
+ @param[in] ChecksumLen - The length of data to be checksumed
+
+ @retval EFI_SUCCESS - Checksum correct
+ @retval EFI_CRC_ERROR - Checksum incorrect
+**/
+EFI_STATUS
+Checksum32Verify (
+ IN UINT32 *ChecksumAddr,
+ IN UINT32 ChecksumLen
+ )
+{
+#if SKIP_MICROCODE_CHECKSUM_CHECK
+ return EFI_SUCCESS;
+#else
+ UINT32 Checksum;
+ UINT32 Index;
+
+ Checksum = 0;
+
+ for (Index = 0; Index < ChecksumLen; Index++) {
+ Checksum += ChecksumAddr[Index];
+ }
+
+ return (Checksum == 0) ? EFI_SUCCESS : EFI_CRC_ERROR;
+#endif
+}
+
+/**
+ Find microcode data
+
+ @param[in] Cpuid - processor CPUID
+ @param[in] MicrocodePointerBuffer - the pointer for microcode buffer
+ @param[in] Revision - revision of microcode
+
+ @retval The pointer of microcode header
+**/
+EFI_CPU_MICROCODE_HEADER *
+FindMicrocode (
+ IN UINTN Cpuid,
+ IN EFI_CPU_MICROCODE_HEADER **MicrocodePointerBuffer,
+ IN UINT32 *Revision
+ )
+{
+ EFI_STATUS Status;
+ EFI_CPU_MICROCODE_HEADER *MicrocodeEntryPoint;
+ UINT8 Index;
+ UINT8 ExtendedIndex;
+ UINT8 MsrPlatform;
+ UINT32 ExtendedTableLength;
+ UINT32 ExtendedTableCount;
+ BOOLEAN CorrectMicrocode;
+ EFI_CPU_MICROCODE_EXTENDED_TABLE *ExtendedTable;
+ EFI_CPU_MICROCODE_EXTENDED_TABLE_HEADER *ExtendedTableHeader;
+
+ Status = EFI_NOT_FOUND;
+ ExtendedTableLength = 0;
+ MicrocodeEntryPoint = NULL;
+ CorrectMicrocode = FALSE;
+
+ ///
+ /// The index of platform information resides in bits 50:52 of MSR IA32_PLATFORM_ID
+ ///
+ MsrPlatform = (UINT8) (RShiftU64 (AsmReadMsr64 (MSR_IA32_PLATFORM_ID), 50) & 0x07);
+
+ Index = 0;
+ while (MicrocodePointerBuffer[Index] != NULL) {
+ MicrocodeEntryPoint = MicrocodePointerBuffer[Index];
+ CorrectMicrocode = FALSE;
+ ///
+ /// Check if the microcode is for the Cpu and the version is newer
+ /// and the update can be processed on the platform
+ ///
+ if ((MicrocodeEntryPoint->HeaderVersion == 0x00000001) &&
+ !EFI_ERROR (CheckMcuRevision (MicrocodeEntryPoint, *Revision))
+ ) {
+ if ((MicrocodeEntryPoint->ProcessorId == Cpuid) && (MicrocodeEntryPoint->ProcessorFlags & (1 << MsrPlatform))) {
+ if (MicrocodeEntryPoint->DataSize == 0) {
+ Status = Checksum32Verify ((UINT32 *) MicrocodeEntryPoint, 2048 / sizeof (UINT32));
+ } else {
+ Status = Checksum32Verify (
+ (UINT32 *) MicrocodeEntryPoint,
+ (MicrocodeEntryPoint->DataSize + sizeof (EFI_CPU_MICROCODE_HEADER)) / sizeof (UINT32)
+ );
+ }
+
+ if (!EFI_ERROR (Status)) {
+ CorrectMicrocode = TRUE;
+ }
+ } else if ((MicrocodeEntryPoint->DataSize != 0)) {
+ ///
+ /// Check the Extended Signature if the entended signature exist
+ /// Only the data size != 0 the extended signature may exist
+ ///
+ ExtendedTableLength = MicrocodeEntryPoint->TotalSize - (MicrocodeEntryPoint->DataSize + sizeof (EFI_CPU_MICROCODE_HEADER));
+ if (ExtendedTableLength != 0) {
+ ///
+ /// Extended Table exist, check if the CPU in support list
+ ///
+ ExtendedTableHeader = (EFI_CPU_MICROCODE_EXTENDED_TABLE_HEADER *) ((UINT8 *) (MicrocodeEntryPoint) + MicrocodeEntryPoint->DataSize + 48);
+ ///
+ /// Calulate Extended Checksum
+ ///
+ if ((ExtendedTableLength % 4) == 0) {
+ Status = Checksum32Verify ((UINT32 *) ExtendedTableHeader, ExtendedTableLength / sizeof (UINT32));
+ if (!EFI_ERROR (Status)) {
+ ///
+ /// Checksum correct
+ ///
+ ExtendedTableCount = ExtendedTableHeader->ExtendedSignatureCount;
+ ExtendedTable = (EFI_CPU_MICROCODE_EXTENDED_TABLE *) (ExtendedTableHeader + 1);
+ for (ExtendedIndex = 0; ExtendedIndex < ExtendedTableCount; ExtendedIndex++) {
+ ///
+ /// Verify Header
+ ///
+ if ((ExtendedTable->ProcessorSignature == Cpuid) && (ExtendedTable->ProcessorFlag & (1 << MsrPlatform))) {
+ Status = Checksum32Verify (
+ (UINT32 *) ExtendedTable,
+ sizeof (EFI_CPU_MICROCODE_EXTENDED_TABLE) / sizeof (UINT32)
+ );
+ if (!EFI_ERROR (Status)) {
+ ///
+ /// Find one
+ ///
+ CorrectMicrocode = TRUE;
+ break;
+ }
+ }
+
+ ExtendedTable++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (CorrectMicrocode) {
+ break;
+ }
+
+ Index += 2;
+ }
+
+ if (!CorrectMicrocode) {
+ MicrocodeEntryPoint = NULL;
+ }
+
+ return MicrocodeEntryPoint;
+}
+
+/**
+ This will locate a processor microcode and if it finds a newer revision, it will
+ load it to the processor.
+
+ @param[in] Cpuid - Data returned by cpuid instruction
+ @param[in] MicrocodePointerBuffer - The Array of pointers which each points to 1 microcode update binary (in memory)
+ @param[in] Revision - As input parameter, the current microcode revision;
+ as output parameter, the microcode revision after microcode update is loaded
+
+ @retval EFI_SUCCESS - A new microcode update is loaded
+ @retval Other - Due to some reason, no new microcode update is loaded
+**/
+EFI_STATUS
+FindLoadMicrocode (
+ IN UINT32 Cpuid,
+ IN EFI_CPU_MICROCODE_HEADER **MicrocodePointerBuffer,
+ IN OUT UINT32 *Revision
+ )
+{
+ EFI_STATUS Status;
+ EFI_CPU_MICROCODE_HEADER *MicrocodeEntryPoint;
+
+ Status = EFI_NOT_FOUND;
+
+ MicrocodeEntryPoint = FindMicrocode (
+ Cpuid,
+ MicrocodePointerBuffer,
+ Revision
+ );
+
+ if (MicrocodeEntryPoint != NULL) {
+ Status = LoadMicrocode (MicrocodeEntryPoint, Revision);
+ *Revision = MicrocodeEntryPoint->UpdateRevision;
+ }
+
+ return Status;
+}
diff --git a/ReferenceCode/Haswell/CpuS3/Pei/MpCommon.h b/ReferenceCode/Haswell/CpuS3/Pei/MpCommon.h
new file mode 100644
index 0000000..63a28d7
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuS3/Pei/MpCommon.h
@@ -0,0 +1,275 @@
+/** @file
+ some definitions for MP and HT driver.
+
+@copyright
+ Copyright (c) 2005 - 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
+**/
+#ifndef _MP_COMMON_
+#define _MP_COMMON_
+
+#include "Tiano.h"
+#include "EfiCombinationLib.h"
+#include "CpuAccess.h"
+#include "CpuPlatformLib.h"
+#include "EdkIIGlueBaseLib.h"
+
+///
+/// Protocol produced by this driver
+///
+/// #include EFI_PROTOCOL_PRODUCER (MpService)
+///
+/// Protocol consumed by this driver
+///
+#include EFI_PPI_DEPENDENCY (Stall)
+#include EFI_GUID_DEFINITION (SmramCpuDataHeader)
+#include EFI_PPI_DEFINITION (CpuPlatformPolicy)
+
+#define VacantFlag 0x00
+#define NotVacantFlag 0xff
+
+#define MICROSECOND 10
+
+#define MAXIMUM_CPU_NUMBER 0x40
+#define STACK_SIZE_PER_PROC 0x8000
+
+#define MAXIMUM_CPU_S3_TABLE_SIZE 0x1000
+
+#define IO_APIC_INDEX_REGISTER 0xFEC00000
+#define IO_APIC_DATA_REGISTER 0xFEC00010
+extern UINTN FixedMtrrNumber;
+extern UINTN MtrrDefTypeNumber;
+extern UINTN VariableMtrrNumber;
+
+typedef struct {
+ UINT16 Index;
+ UINT64 Value;
+} EFI_MTRR_VALUES;
+
+typedef struct {
+ UINT32 ApicId;
+ UINT32 MsrIndex;
+ UINT64 MsrValue;
+} MP_CPU_S3_SCRIPT_DATA;
+
+typedef struct {
+ UINT32 S3BootScriptTable;
+ UINT32 S3BspMtrrTable;
+ UINT32 VirtualWireMode;
+} MP_CPU_S3_DATA_POINTER;
+
+typedef struct {
+ UINT32 Lock;
+ UINT32 StackStart;
+ UINT32 StackSize;
+ UINT32 ApFunction;
+ PSEUDO_DESCRIPTOR GdtrProfile;
+ PSEUDO_DESCRIPTOR IdtrProfile;
+ UINT32 BufferStart;
+ UINT32 PmodeOffset;
+ UINT32 AcpiCpuDataAddress;
+ UINT32 MtrrValuesAddress;
+ UINT32 FinishedCount;
+ UINT32 WakeupCount;
+ UINT32 SerializeLock;
+ UINT32 MicrocodePointer;
+ MP_CPU_S3_SCRIPT_DATA *S3BootScriptTable;
+ UINT32 StartState;
+ UINT32 VirtualWireMode;
+ VOID (*SemaphoreCheck)(
+ UINT32 *SemaphoreAddress
+ );
+ UINT32 McuLoadCount;
+ EFI_PEI_SERVICES **PeiServices;
+ PEI_STALL_PPI *PeiStall;
+ UINT64 CpuPerfCtrlValue;
+ PEI_CPU_PLATFORM_POLICY_PPI *CpuPlatformPolicyPpi;
+} MP_CPU_EXCHANGE_INFO;
+
+/**
+ Get protected mode code offset
+
+ @retval Offset of protected mode code
+**/
+VOID *
+AsmGetPmodeOffset (
+ VOID
+ );
+
+/**
+ Get code offset of SemaphoreCheck
+
+ @retval Offset of SemaphoreCheck
+**/
+UINT32
+AsmGetSemaphoreCheckOffset (
+ VOID
+ );
+
+/**
+ Read MTRR settings
+
+ @param[in] PeiServices - General purpose services available to every PEIM.
+ @param[in] MtrrValues - buffer to store MTRR settings
+**/
+VOID
+ReadMtrrRegisters (
+ IN EFI_PEI_SERVICES **PeiServices,
+ UINT64 *MtrrValues
+ );
+
+/**
+ Syncup MTRR settings between all processors
+
+ @param[in] MtrrValues - buffer to store MTRR settings
+**/
+VOID
+MpMtrrSynchUp (
+ UINT64 *MtrrValues
+ );
+
+/**
+ Set MTRR registers
+
+ @param[in] PeiServices - General purpose services available to every PEIM.
+ @param[in] MtrrArray - buffer with MTRR settings
+**/
+VOID
+SetMtrrRegisters (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_MTRR_VALUES *MtrrArray
+ );
+
+#ifdef EFI_DEBUG
+/**
+ Print MTRR settings in debug build BIOS
+
+ @param[in] PeiServices - General purpose services available to every PEIM.
+ @param[in] MtrrArray - buffer with MTRR settings
+**/
+VOID
+ShowMtrrRegisters (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_MTRR_VALUES *MtrrArray
+ );
+#endif
+
+/**
+ This will locate a processor microcode and if it finds a newer revision, it will
+ load it to the processor.
+
+ @param[in] ExchangeInfo - Pointer to the exchange info buffer for output.
+ @param[in] MicrocodePointerBuffer - The Array of pointers which each points to 1 microcode update binary (in memory)
+ @param[in] FailedRevision - The microcode revision that fails to be loaded
+
+ @retval EFI_SUCCESS - A new microcode update is loaded
+ @retval Other - Due to some reason, no new microcode update is loaded
+**/
+EFI_STATUS
+InitializeMicrocode (
+ IN MP_CPU_EXCHANGE_INFO *ExchangeInfo,
+ IN EFI_CPU_MICROCODE_HEADER **MicrocodePointerBuffer,
+ OUT UINT32 *FailedRevision
+ );
+
+///
+/// Functions shared in MP/HT drivers
+///
+/**
+ Send interrupt to CPU
+
+ @param[in] BroadcastMode - interrupt broadcast mode
+ @param[in] ApicID - APIC ID for sending interrupt
+ @param[in] VectorNumber - Vector number
+ @param[in] DeliveryMode - Interrupt delivery mode
+ @param[in] TriggerMode - Interrupt trigger mode
+ @param[in] Assert - Interrupt pin polarity
+ @param[in] PeiServices - Indirect reference to the PEI Services Table
+ @param[in] PeiStall - EFI_PEI_STALL_PPI to stall for some interval
+
+ @retval EFI_INVALID_PARAMETER - input parameter not correct
+ @retval EFI_NOT_READY - there was a pending interrupt
+ @retval EFI_SUCCESS - interrupt sent successfully
+**/
+EFI_STATUS
+SendInterrupt (
+ IN UINT32 BroadcastMode,
+ IN UINT32 ApicID,
+ IN UINT32 VectorNumber,
+ IN UINT32 DeliveryMode,
+ IN UINT32 TriggerMode,
+ IN BOOLEAN Assert,
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_STALL_PPI *PeiStall
+ );
+
+/**
+ Get APIC ID of processor
+
+ @retval APIC ID of processor
+**/
+UINT32
+GetApicID (
+ VOID
+ );
+
+/**
+ Programs Local APIC registers for virtual wire mode.
+
+ @param[in] BSP - Is this BSP?
+**/
+VOID
+ProgramXApic (
+ BOOLEAN BSP
+ );
+
+/**
+ Lock APs
+
+ @param[in] Lock - Lock state
+**/
+VOID
+AsmAcquireMPLock (
+ IN UINT8 *Lock
+ );
+
+/**
+ Release APs
+
+ @param[in] Lock - Lock state
+**/
+VOID
+AsmReleaseMPLock (
+ IN UINT8 *Lock
+ );
+
+/**
+ Get address map of RendezvousFunnelProc.
+
+ @retval AddressMap - Output buffer for address map information
+**/
+VOID *
+AsmGetAddressMap (
+ VOID
+ );
+
+/**
+ Do CLI and HALT processor
+**/
+VOID
+AsmCliHltLoop (
+ VOID
+ );
+
+#endif
diff --git a/ReferenceCode/Haswell/CpuS3/Pei/MpEqu.inc b/ReferenceCode/Haswell/CpuS3/Pei/MpEqu.inc
new file mode 100644
index 0000000..da4b873
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuS3/Pei/MpEqu.inc
@@ -0,0 +1,51 @@
+;@file
+; This is the equates file for HT (Hyper-threading) support
+;
+;@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
+;
+
+VacantFlag Equ 00h
+NotVacantFlag Equ 0ffh
+
+LockLocation equ 1000h - 0200h
+StackStartAddressLocation equ LockLocation + 04h
+StackSizeLocation equ LockLocation + 08h
+CProcedureLocation equ LockLocation + 0Ch
+GdtrLocation equ LockLocation + 10h
+IdtrLocation equ LockLocation + 16h
+BufferStartLocation equ LockLocation + 1Ch
+PmodeOffsetLocation equ LockLocation + 20h
+AcpiCpuDataAddressLocation equ LockLocation + 24h
+MtrrValuesAddressLocation equ LockLocation + 28h
+FinishedCountAddressLocation equ LockLocation + 2Ch
+WakeupCountAddressLocation equ LockLocation + 30h
+SerializeLockAddressLocation equ LockLocation + 34h
+MicrocodeAddressLocation equ LockLocation + 38h
+BootScriptAddressLocation equ LockLocation + 3Ch
+StartStateLocation equ LockLocation + 40h
+VirtualWireMode equ LockLocation + 44h
+SemaphoreCheck equ LockLocation + 48h
+PeiServices equ LockLocation + 4Ch
+PeiStall equ LockLocation + 50h
+CpuPerfCtrlValue equ LockLocation + 54h
+CpuPlatformPolicyPpi equ LockLocation + 5Ch
+
+PAUSE32 MACRO
+ DB 0F3h
+ DB 090h
+ ENDM
+
+;-------------------------------------------------------------------------------
diff --git a/ReferenceCode/Haswell/CpuS3/Pei/MpFuncs.asm b/ReferenceCode/Haswell/CpuS3/Pei/MpFuncs.asm
new file mode 100644
index 0000000..80064c2
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuS3/Pei/MpFuncs.asm
@@ -0,0 +1,196 @@
+;
+; 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 - 2011 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:
+;
+; MpFuncs32.asm
+;
+; Abstract:
+;
+; This is the assembly code for MP support
+;
+;-------------------------------------------------------------------------------
+
+include MpEqu.inc
+
+;-------------------------------------------------------------------------------------
+;RendezvousFunnelProc procedure follows. All APs execute their procedure. This
+;procedure serializes all the AP processors through an Init sequence. It must be
+;noted that APs arrive here very raw...ie: real mode, no stack.
+;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
+;IS IN MACHINE CODE.
+;-------------------------------------------------------------------------------------
+;RendezvousFunnelProc (&WakeUpBuffer,MemAddress);
+
+.686p
+.model flat
+.code
+
+
+RendezvousFunnelProc PROC PUBLIC
+RendezvousFunnelProcStart::
+
+;Step-1: Grab a lock. At this point CS = 0x(vv00) and ip= 0x0.
+
+ db 8ch,0c8h ; mov ax,cs
+ db 8eh,0d8h ; mov ds,ax
+ db 8eh,0c0h ; mov es,ax
+ db 8eh,0d0h ; mov ss,ax
+ db 33h,0c0h ; xor ax,ax
+ db 8eh,0e0h ; mov fs,ax
+ db 8eh,0e8h ; mov gs,ax
+
+ db 0BEh ; opcode of mov si, mem16
+ dw BufferStartLocation ; mov si, BufferStartLocation
+ db 66h, 8Bh, 1Ch ; mov ebx,dword ptr [si]
+
+ db 0BFh ; opcode of mov di, mem16
+ dw PmodeOffsetLocation ; mov di, PmodeOffsetLocation
+ db 66h, 8Bh, 05h ; mov eax,dword ptr [di]
+ db 8Bh, 0F8h ; mov di, ax
+ db 83h, 0EFh,06h ; sub di, 06h
+ db 66h, 03h, 0C3h ; add eax, ebx
+ db 66h, 89h, 05h ; mov dword ptr [di],eax
+
+ db 0BEh ; opcode of mov si, mem16
+ dw GdtrLocation ; mov si, GdtrLocation
+ db 66h ; db 66h
+ db 2Eh, 0Fh, 01h, 14h ; lgdt fword ptr cs:[si]
+
+ db 33h, 0C0h ; xor ax, ax
+ db 8Eh, 0D8h ; mov ds, ax
+
+ db 0Fh, 20h, 0C0h ; mov eax, cr0 ;Get control register 0
+ db 66h, 83h, 0C8h, 03h ; or eax, 000000003h ;Set PE bit (bit #0) & MP
+ db 0Fh, 22h, 0C0h ; mov cr0, eax
+
+ db 66h, 67h, 0EAh ; far jump
+ dd 0h ; 32-bit offset
+ dw 20h ; 16-bit selector
+
+NemInit:: ; protected mode entry point
+
+ db 66h, 0B8h, 18h, 00h ; mov ax, 18h
+ db 66h, 8Eh, 0D8h ; mov ds, ax
+ db 66h, 8Eh, 0C0h ; mov es, ax
+ db 66h, 8Eh, 0E0h ; mov fs, ax
+ db 66h, 8Eh, 0E8h ; mov gs, ax
+ db 66h, 8Eh, 0D0h ; mov ss, ax ; Flat mode setup.
+
+ mov esi, ebx
+
+ mov edi, esi
+ add edi, StartStateLocation
+ mov eax, 1
+ mov dword ptr [edi], eax
+
+ mov edi, esi
+ add edi, LockLocation
+ mov eax, NotVacantFlag
+TestLock::
+ xchg dword ptr [edi], eax
+ cmp eax, NotVacantFlag
+ jz TestLock
+
+ProgramStack::
+
+ mov edi, esi
+ add edi, StackSizeLocation
+ mov eax, dword ptr [edi]
+ mov edi, esi
+ add edi, StackStartAddressLocation
+ add eax, dword ptr [edi]
+ mov esp, eax
+ mov dword ptr [edi], eax
+
+Releaselock::
+
+ mov eax, VacantFlag
+ mov edi, esi
+ add edi, LockLocation
+ xchg dword ptr [edi], eax
+
+CProcedureInvoke::
+
+ mov edi, esi
+ add edi, MtrrValuesAddressLocation
+ mov eax, dword ptr [edi]
+ push eax
+
+ mov eax, esi
+ add eax, LockLocation
+ push eax
+
+ mov edi, esi
+ add edi, CProcedureLocation
+ mov eax, dword ptr [edi]
+
+ call eax
+ add esp, 8
+
+ cli
+ hlt
+ jmp $-2
+
+RendezvousFunnelProc ENDP
+
+SemaphoreStartAddress PROC C, SemaphoreAddress:PTR DWORD
+ mov eax, SemaphoreAddress
+@@:
+ cmp dword ptr [eax], 0
+ jz @F
+
+ PAUSE32
+ jmp @B
+
+@@:
+ ret
+SemaphoreStartAddress ENDP
+
+RendezvousFunnelProcEnd::
+
+
+;-------------------------------------------------------------------------------------
+; AsmGetAddressMap (&AddressMap);
+;-------------------------------------------------------------------------------------
+AsmGetAddressMap PROC near C PUBLIC
+
+ mov eax, RendezvousFunnelProcStart
+ ret
+
+AsmGetAddressMap ENDP
+
+AsmGetPmodeOffset PROC near C PUBLIC
+
+ mov eax, NemInit - RendezvousFunnelProcStart
+ ret
+
+AsmGetPmodeOffset ENDP
+
+AsmGetSemaphoreCheckOffset PROC near C PUBLIC
+ mov eax, SemaphoreStartAddress - RendezvousFunnelProcStart
+ ret
+AsmGetSemaphoreCheckOffset ENDP
+
+AsmCliHltLoop PROC near C PUBLIC
+ cli
+ hlt
+ jmp $-2
+AsmCliHltLoop ENDP
+
+END
diff --git a/ReferenceCode/Haswell/CpuS3/Pei/MtrrSync.c b/ReferenceCode/Haswell/CpuS3/Pei/MtrrSync.c
new file mode 100644
index 0000000..96e47ee
--- /dev/null
+++ b/ReferenceCode/Haswell/CpuS3/Pei/MtrrSync.c
@@ -0,0 +1,288 @@
+/** @file
+ Synchronization of MTRRs on S3 boot path.
+
+@copyright
+ Copyright (c) 2005 - 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
+**/
+
+///
+/// External include files do NOT need to be explicitly specified in real EDKII
+/// environment
+///
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGluePeim.h"
+#include "CpuAccess.h"
+#include "MpCommon.h"
+#endif
+
+UINTN
+MpMtrrSynchUpEntry (
+ VOID
+ );
+
+VOID
+MpMtrrSynchUpExit (
+ UINTN Cr4
+ );
+
+UINT16 mFixedMtrrIndex[] = {
+ IA32_MTRR_FIX64K_00000,
+ IA32_MTRR_FIX16K_80000,
+ IA32_MTRR_FIX16K_A0000,
+ IA32_MTRR_FIX4K_C0000,
+ IA32_MTRR_FIX4K_C8000,
+ IA32_MTRR_FIX4K_D0000,
+ IA32_MTRR_FIX4K_D8000,
+ IA32_MTRR_FIX4K_E0000,
+ IA32_MTRR_FIX4K_E8000,
+ IA32_MTRR_FIX4K_F0000,
+ IA32_MTRR_FIX4K_F8000,
+};
+
+UINT16 mMtrrDefType[] = { CACHE_IA32_MTRR_DEF_TYPE };
+
+UINT16 mVariableMtrrIndex[] = {
+ CACHE_VARIABLE_MTRR_BASE,
+ CACHE_VARIABLE_MTRR_BASE + 1,
+ CACHE_VARIABLE_MTRR_BASE + 2,
+ CACHE_VARIABLE_MTRR_BASE + 3,
+ CACHE_VARIABLE_MTRR_BASE + 4,
+ CACHE_VARIABLE_MTRR_BASE + 5,
+ CACHE_VARIABLE_MTRR_BASE + 6,
+ CACHE_VARIABLE_MTRR_BASE + 7,
+ CACHE_VARIABLE_MTRR_BASE + 8,
+ CACHE_VARIABLE_MTRR_BASE + 9,
+ CACHE_VARIABLE_MTRR_BASE + 10,
+ CACHE_VARIABLE_MTRR_BASE + 11,
+ CACHE_VARIABLE_MTRR_BASE + 12,
+ CACHE_VARIABLE_MTRR_BASE + 13,
+ CACHE_VARIABLE_MTRR_BASE + 14,
+ CACHE_VARIABLE_MTRR_BASE + 15,
+ CACHE_VARIABLE_MTRR_BASE + 16,
+ CACHE_VARIABLE_MTRR_BASE + 17,
+ CACHE_VARIABLE_MTRR_BASE + 18,
+ CACHE_VARIABLE_MTRR_BASE + 19,
+ ///
+ /// CACHE_VARIABLE_MTRR_END,
+ ///
+};
+
+UINTN FixedMtrrNumber = sizeof (mFixedMtrrIndex) / sizeof (UINT16);
+UINTN MtrrDefTypeNumber = sizeof (mMtrrDefType) / sizeof (UINT16);
+
+/**
+ Save the MTRR registers to global variables
+
+ @param[in] PeiServices - Indirect reference to the PEI Services Table
+ @param[in] MtrrValues - pointer to the buffer which stores MTRR settings
+**/
+VOID
+ReadMtrrRegisters (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN UINT64 *MtrrValues
+ )
+{
+ UINT32 Index;
+ UINT32 VariableMtrrNumber;
+ ///
+ /// Read all Mtrrs
+ ///
+ for (Index = 0; Index < FixedMtrrNumber; Index++) {
+ *MtrrValues = AsmReadMsr64 (mFixedMtrrIndex[Index]);
+ MtrrValues++;
+ }
+
+ for (Index = 0; Index < MtrrDefTypeNumber; Index++) {
+ *MtrrValues = AsmReadMsr64 (mMtrrDefType[Index]);
+ MtrrValues++;
+ }
+
+ VariableMtrrNumber = ((UINT32) (AsmReadMsr64 (IA32_MTRR_CAP) & B_IA32_MTRR_VARIABLE_SUPPORT));
+ if (VariableMtrrNumber > V_MAXIMUM_VARIABLE_MTRR_NUMBER) {
+ VariableMtrrNumber = V_MAXIMUM_VARIABLE_MTRR_NUMBER;
+ }
+
+ DEBUG ((EFI_D_INFO, "MTRR: VariableMtrrNumber = %x\n", VariableMtrrNumber));
+ for (Index = 0; Index < VariableMtrrNumber * 2; Index++) {
+ *MtrrValues = AsmReadMsr64 (mVariableMtrrIndex[Index]);
+ MtrrValues++;
+ DEBUG (
+ (EFI_D_INFO,
+ "MTRR: Index = %x AsmReadMsr64(%x) = %x\n",
+ Index,
+ mVariableMtrrIndex[Index],
+ AsmReadMsr64 (mVariableMtrrIndex[Index]))
+ );
+ }
+
+ return;
+}
+
+/**
+ Synch up the MTRR values for all processors
+
+ @param[in] MtrrValues - pointer to the buffer which stores MTRR settings
+**/
+VOID
+MpMtrrSynchUp (
+ UINT64 *MtrrValues
+ )
+{
+ UINT32 Index;
+ UINT32 VariableMtrrNumber;
+ UINTN Cr4;
+ UINT64 *FixedMtrr;
+ UINT64 *MtrrDefType;
+ UINT64 *VariableMtrr;
+ UINT64 ValidMtrrAddressMask;
+ EFI_CPUID_REGISTER FeatureInfo;
+ EFI_CPUID_REGISTER FunctionInfo;
+ UINT8 PhysicalAddressBits;
+
+ ///
+ /// Get physical CPU MTRR width in case of difference from BSP
+ ///
+ AsmCpuid (
+ CPUID_EXTENDED_FUNCTION,
+ &FunctionInfo.RegEax,
+ &FunctionInfo.RegEbx,
+ &FunctionInfo.RegEcx,
+ &FunctionInfo.RegEdx
+ );
+ PhysicalAddressBits = 36;
+ if (FunctionInfo.RegEax >= CPUID_VIR_PHY_ADDRESS_SIZE) {
+ AsmCpuid (
+ CPUID_VIR_PHY_ADDRESS_SIZE,
+ &FeatureInfo.RegEax,
+ &FeatureInfo.RegEbx,
+ &FeatureInfo.RegEcx,
+ &FeatureInfo.RegEdx
+ );
+ PhysicalAddressBits = (UINT8) FeatureInfo.RegEax;
+ }
+
+ ValidMtrrAddressMask = (LShiftU64 (1, PhysicalAddressBits) - 1) & 0xfffffffffffff000ULL;
+
+ FixedMtrr = MtrrValues;
+ MtrrDefType = MtrrValues + FixedMtrrNumber;
+ VariableMtrr = MtrrValues + FixedMtrrNumber + MtrrDefTypeNumber;
+
+ ///
+ /// ASM code to setup processor register before synching up the MTRRs
+ ///
+ Cr4 = MpMtrrSynchUpEntry ();
+
+ ///
+ /// Disable Fixed Mtrrs
+ ///
+ AsmWriteMsr64 (CACHE_IA32_MTRR_DEF_TYPE, MtrrDefType[0] & 0xFFFFF7FF);
+
+ ///
+ /// Update Fixed Mtrrs
+ ///
+ for (Index = 0; Index < FixedMtrrNumber; Index++) {
+ AsmWriteMsr64 (mFixedMtrrIndex[Index], FixedMtrr[Index]);
+ }
+ ///
+ /// Synchup Base Variable Mtrr
+ ///
+ VariableMtrrNumber = (UINT32) (AsmReadMsr64 (IA32_MTRR_CAP) & B_IA32_MTRR_VARIABLE_SUPPORT);
+ if (VariableMtrrNumber > V_MAXIMUM_VARIABLE_MTRR_NUMBER) {
+ VariableMtrrNumber = V_MAXIMUM_VARIABLE_MTRR_NUMBER;
+ }
+
+ for (Index = 0; Index < VariableMtrrNumber * 2; Index++) {
+ AsmWriteMsr64 (
+ mVariableMtrrIndex[Index],
+ (VariableMtrr[Index] & 0x0FFF) | (VariableMtrr[Index] & ValidMtrrAddressMask)
+ );
+ }
+ ///
+ /// Synchup def type Fixed Mtrrs
+ ///
+ AsmWriteMsr64 (CACHE_IA32_MTRR_DEF_TYPE, MtrrDefType[0]);
+
+ ///
+ /// ASM code to setup processor register after synching up the MTRRs
+ ///
+ MpMtrrSynchUpExit (Cr4);
+
+ return;
+}
+
+/**
+ Set MTRR registers
+
+ @param[in] PeiServices - General purpose services available to every PEIM.
+ @param[in] MtrrArray - buffer with MTRR settings
+**/
+VOID
+SetMtrrRegisters (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_MTRR_VALUES *MtrrArray
+ )
+{
+ UINT32 Index;
+ UINTN Cr4;
+
+ ///
+ /// ASM code to setup processor register before synching up the MTRRs
+ ///
+ Cr4 = MpMtrrSynchUpEntry ();
+
+ Index = 0;
+ while ((MtrrArray[Index].Index != 0) && (MtrrArray[Index].Index >= CACHE_VARIABLE_MTRR_BASE)) {
+ AsmWriteMsr64 (MtrrArray[Index].Index, MtrrArray[Index].Value);
+ Index++;
+ }
+ ///
+ /// ASM code to setup processor register after synching up the MTRRs
+ ///
+ MpMtrrSynchUpExit (Cr4);
+}
+
+#ifdef EFI_DEBUG
+/**
+ Print MTRR settings in debug build BIOS
+
+ @param[in] PeiServices - General purpose services available to every PEIM.
+ @param[in] MtrrArray - buffer with MTRR settings
+**/
+VOID
+ShowMtrrRegisters (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_MTRR_VALUES *MtrrArray
+ )
+{
+ UINT32 Index;
+
+ Index = 0;
+ while ((MtrrArray[Index].Index != 0) && (MtrrArray[Index].Index >= CACHE_VARIABLE_MTRR_BASE)) {
+
+ DEBUG ((EFI_D_INFO, "MTRR: MtrrArray Index = %x\n", Index));
+ DEBUG (
+ (EFI_D_INFO,
+ "MTRR: MtrrArray[%x].Index = %x MtrrArray[%x].Value = %x\n",
+ Index,
+ MtrrArray[Index].Index,
+ Index,
+ MtrrArray[Index].Value)
+ );
+ Index++;
+ }
+
+ DEBUG ((EFI_D_INFO, "MTRR: Total Index = %x\n", Index));
+}
+#endif
diff --git a/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorInitStatus.h b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorInitStatus.h
new file mode 100644
index 0000000..24149b0
--- /dev/null
+++ b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorInitStatus.h
@@ -0,0 +1,46 @@
+/** @file
+ This protocol is used to get the status of Digital Thermal Sensor driver initialization
+
+@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 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
+**/
+#ifndef _DTS_INIT_STATUS_PROTOCOL_H_
+#define _DTS_INIT_STATUS_PROTOCOL_H_
+
+///
+/// Define protocol GUID
+///
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#define DTS_INIT_STATUS_PROTOCOL_GUID \
+ { \
+ 0xf687f441, 0x7dcf, 0x4f45, 0x8f, 0x64, 0xca, 0xf2, 0x88, 0xea, 0x50, 0x4e \
+ }
+#else
+#define DTS_INIT_STATUS_PROTOCOL_GUID \
+ { \
+ 0xf687f441, 0x7dcf, 0x4f45, \
+ { \
+ 0x8f, 0x64, 0xca, 0xf2, 0x88, 0xea, 0x50, 0x4e \
+ } \
+ }
+#endif
+
+typedef struct _DTS_INIT_STATUS_PROTOCOL {
+ BOOLEAN IsDtsInitComplete;
+} DTS_INIT_STATUS_PROTOCOL;
+
+#endif
diff --git a/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorLib.h b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorLib.h
new file mode 100644
index 0000000..52fe54c
--- /dev/null
+++ b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorLib.h
@@ -0,0 +1,62 @@
+/** @file
+ Defines and prototypes for the DigitalThermalSensor SMM driver
+
+@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 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
+**/
+
+#ifndef _DIGITAL_THERMAL_SENSOR_LIB_H_
+#define _DIGITAL_THERMAL_SENSOR_LIB_H_
+
+/**
+ Prepare data and protocol for Dts Hooe Lib
+
+ @retval EFI_SUCCESS - Initialize complete
+**/
+EFI_STATUS
+InitializeDtsHookLib (
+ VOID
+ );
+
+/**
+ Platform may need to register some data to private data structure before generate
+ software SMI or SCI.
+**/
+VOID
+PlatformHookBeforeGenerateSCI (
+ VOID
+ );
+
+/**
+ Read CPU temperature from platform diode
+
+ @retval TemperatureOfDiode - Return the CPU temperature of platform diode
+**/
+UINT8
+ReadPlatformThermalDiode (
+ VOID
+ );
+
+/**
+ When system temperature out of specification, do platform specific programming to prevent
+ system damage.
+**/
+VOID
+PlatformEventOutOfSpec (
+ VOID
+ );
+
+#endif
diff --git a/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.c b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.c
new file mode 100644
index 0000000..38dad6c
--- /dev/null
+++ b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.c
@@ -0,0 +1,1536 @@
+/** @file
+ Digital Thermal Sensor (DTS) driver.
+ This SMM driver configures and supports the Digital Thermal Sensor features for the platform.
+
+@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 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
+
+**/
+#include "DigitalThermalSensorSmm.h"
+#include "KscLib.h"
+//
+// Protocol GUID definition
+//
+DXE_CPU_PLATFORM_POLICY_PROTOCOL *mPlatformCpu = NULL;
+
+EFI_GUID gDtsInitStatusProtocolGuid = DTS_INIT_STATUS_PROTOCOL_GUID;
+EFI_GUID mEfiGlobalNvsAreaProtocolGuid = EFI_GLOBAL_NVS_AREA_PROTOCOL_GUID;
+EFI_GUID mEfiSmmIoTrapDispatchProtocolGuid = EFI_SMM_IO_TRAP_DISPATCH_PROTOCOL_GUID;
+DTS_INIT_STATUS_PROTOCOL mDtsInitStatusProtocol;
+
+//
+// Global variables
+//
+EFI_SMM_BASE_PROTOCOL *mSmmBase;
+EFI_SMM_SYSTEM_TABLE *mSmst;
+
+EFI_GLOBAL_NVS_AREA *mGlobalNvsAreaPtr;
+UINT8 DTSSetupValue;
+
+BOOLEAN mDtsEnabled;
+UINT8 mDtsTjMax;
+UINT16 mAcpiBaseAddr;
+BOOLEAN mUpdateDtsInEverySmi;
+UINT8 mNoOfThresholdRanges;
+UINT8 (*mDtsThresholdTable)[3];
+UINT8 gIsPackageTempMsrAvailable;
+///
+/// The table is updated for the current CPU.
+///
+UINT8 mDigitalThermalSensorThresholdTable[DTS_NUMBER_THRESHOLD_RANGES][3] = {
+ ///
+ /// TJ_MAX = 110 ///< Current Temp. Low Temp. High Temp.
+ ///
+ {TJ_MAX-80,100,75}, ///< <= 30 10 35
+ {TJ_MAX-70,85,65}, ///< 30 ~ 39 25 45
+ {TJ_MAX-60,75,55}, ///< 40 ~ 49 35 55
+ {TJ_MAX-50,65,45}, ///< 50 ~ 59 45 65
+ {TJ_MAX-40,55,35}, ///< 60 ~ 69 55 75
+ {TJ_MAX-30,45,25}, ///< 70 ~ 79 65 85
+ {TJ_MAX-20,35,15}, ///< 80 ~ 89 75 95
+ {TJ_MAX-10,25,05}, ///< 90 ~ 99 85 105
+ {TJ_MAX-00,15,00} ///< 100 ~ 109 95 110
+};
+
+//
+// Function implementations
+//
+/**
+ Read the temperature data per core/thread.
+ This function must be AP safe.
+
+ @param[in] Buffer Pointer to UINT8 to update with the current temperature
+
+ @retval EFI_SUCCESS Digital Thermal Sensor temperature has updated successfully.
+**/
+VOID
+EFIAPI
+DigitalThermalSensorUpdateTemperature (
+ VOID *Buffer
+ )
+{
+ MSR_REGISTER MsrData;
+ UINT8 Temperature;
+ UINT8 DefApicId;
+ EFI_CPUID_REGISTER CpuidRegisters;
+ UINT8 *TempPointer;
+
+ AsmCpuid (
+ EFI_CPUID_VERSION_INFO,
+ &CpuidRegisters.RegEax,
+ &CpuidRegisters.RegEbx,
+ &CpuidRegisters.RegEcx,
+ &CpuidRegisters.RegEdx
+ );
+ ///
+ /// Default APIC ID = CPUID Function 01, EBX[31:24]
+ ///
+ DefApicId = (UINT8) RShiftU64 (CpuidRegisters.RegEbx, 24);
+
+ ///
+ /// Read the temperature
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_IA32_THERM_STATUS);
+
+ ///
+ /// Find the DTS temperature.
+ ///
+ Temperature = mDtsTjMax - (MsrData.Bytes.ThirdByte & OFFSET_MASK);
+ ///
+ /// We only update the temperature if it is above the current temperature.
+ ///
+ TempPointer = Buffer;
+ if (Temperature > *((UINT8 *) (TempPointer + DefApicId))) {
+ *((UINT8 *) (TempPointer + DefApicId)) = Temperature;
+ }
+
+ return;
+}
+
+/**
+ Read the temperature and update the data for PTID support.
+
+ @retval EFI_SUCCESS Digital Thermal Sensor temperature has updated successfully.
+**/
+EFI_STATUS
+DigitalThermalSensorUpdatePTID (
+ VOID
+ )
+{
+ ///
+ /// ThreadTemperatureBuffer[0], [2], [4] and [6] are Thread0 and [1], [3], [5] and [7] are Thread1 for each Core.
+ /// If thread or core not active, this thread/core temperature will be reported as 0
+ ///
+ UINT8 ThreadTemperatureBuffer[MAX_NUMBER_OF_THREADS_SUPPORTED];
+ UINT8 Index;
+ UINT8 CoreTemp[MAX_NUMBER_OF_THREADS_SUPPORTED / 2];
+
+ ///
+ /// Get DTS temperature for all cores/threads.
+ ///
+ for (Index = 0; Index < MAX_NUMBER_OF_THREADS_SUPPORTED; Index++) {
+ ThreadTemperatureBuffer[Index] = 0;
+ }
+
+ RunOnAllLogicalProcessors (DigitalThermalSensorUpdateTemperature, ThreadTemperatureBuffer);
+ ///
+ /// Compare thread1 and thread2 temperature in each core and only report higher temperature as core temperature.
+ ///
+ for (Index = 0; Index < MAX_NUMBER_OF_THREADS_SUPPORTED; Index += 2) {
+ CoreTemp[(UINT8) DivU64x32 (Index, 2)] =
+ (ThreadTemperatureBuffer[Index] > ThreadTemperatureBuffer[Index + 1])
+ ? ThreadTemperatureBuffer[Index] : ThreadTemperatureBuffer[Index + 1];
+ }
+
+ mGlobalNvsAreaPtr->BspDigitalThermalSensorTemperature = CoreTemp[0];
+ if ((MAX_NUMBER_OF_THREADS_SUPPORTED / 2) > 1) {
+ mGlobalNvsAreaPtr->ApDigitalThermalSensorTemperature = CoreTemp[1];
+ }
+
+ if ((MAX_NUMBER_OF_THREADS_SUPPORTED / 2) > 2) {
+ mGlobalNvsAreaPtr->Ap2DigitalThermalSensorTemperature = CoreTemp[2];
+ }
+
+ if ((MAX_NUMBER_OF_THREADS_SUPPORTED / 2) > 3) {
+ mGlobalNvsAreaPtr->Ap3DigitalThermalSensorTemperature = CoreTemp[3];
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ SMI handler to handle Digital Thermal Sensor CPU Local APIC SMI
+ for thermal Out Of Spec interrupt
+
+ @param[in] SmmImageHandle Image handle returned by the SMM driver.
+ @param[in] CommunicationBuffer Pointer to the buffer that contains the communication Message
+ @param[in] SourceSize Size of the memory image to be used for handler.
+
+ @retval EFI_SUCCESS Callback Function Executed
+**/
+EFI_STATUS
+EFIAPI
+DtsOutOfSpecSmiCallback (
+ IN EFI_HANDLE SmmImageHandle,
+ IN OUT VOID *CommunicationBuffer,
+ IN OUT UINTN *SourceSize
+ )
+{
+
+ DTS_EVENT_TYPE EventType;
+
+ ///
+ /// If not enabled; return. (The DTS will be disabled upon S3 entry
+ /// and will remain disabled until after re-initialized upon wake.)
+ ///
+ if (!mDtsEnabled) {
+ return EFI_SUCCESS;
+ }
+
+ EventType = DtsEventNone;
+
+ if (gIsPackageTempMsrAvailable) {
+ ///
+ /// Get the Package DTS Event Type
+ ///
+ DigitalThermalSensorEventCheckPackageMsr (&EventType);
+ } else {
+ ///
+ /// Get the DTS Event Type
+ ///
+ DigitalThermalSensorEventCheck (&EventType);
+ }
+ ///
+ /// Check if this a DTS Out Of Spec SMI event
+ ///
+ if (EventType == DtsEventOutOfSpec) {
+ ///
+ /// Return Critical temperature value to _TMP and generate GPE event for critical shutdown.
+ ///
+ mGlobalNvsAreaPtr->EnableDigitalThermalSensor = DTS_OUT_OF_SPEC_OCCURRED;
+
+ ///
+ /// Generate SCI to shut down the system
+ ///
+ DigitalThermalSensorSetSwGpeSts ();
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Call from SMI handler to handle Package thermal temperature Digital Thermal Sensor CPU Local APIC SMI
+ for thermal threshold interrupt
+
+ @retval None
+**/
+VOID
+PackageThermalDTS (
+ VOID
+ )
+{
+ DTS_EVENT_TYPE PkgEventType;
+
+ PkgEventType = DtsEventNone;
+
+ ///
+ /// Check is this a Platform SMI event or the flag of update DTS temperature and threshold value in every SMI
+ ///
+ if (DigitalThermalSensorEventCheckPackageMsr (&PkgEventType) || mUpdateDtsInEverySmi) {
+ ///
+ /// Disable Local APIC SMI before programming the threshold
+ ///
+ RunOnAllLogicalProcessors (DigitalThermalSensorDisableSmi, NULL);
+
+ do {
+ ///
+ /// Handle Package events
+ ///
+ if ((PkgEventType == DtsEventOutOfSpec) && (mGlobalNvsAreaPtr->OperatingSystem == 0)) {
+ ///
+ /// Handle critical event by shutting down via EC if ACPI
+ /// is not enabled.
+ ///
+ PlatformEventOutOfSpec ();
+ }
+ ///
+ /// Set the thermal trip toints as needed.
+ ///
+ mGlobalNvsAreaPtr->PackageDTSTemperature = 0;
+
+ ///
+ /// Set the Package thermal sensor thresholds
+ ///
+ PackageDigitalThermalSensorSetThreshold (&mGlobalNvsAreaPtr->PackageDTSTemperature);
+
+ ///
+ /// Set SWGPE Status to generate an SCI if we had any events
+ ///
+ if ((PkgEventType != DtsEventNone) || mUpdateDtsInEverySmi) {
+ DigitalThermalSensorSetSwGpeSts ();
+ }
+
+ } while (DigitalThermalSensorEventCheckPackageMsr (&PkgEventType));
+ ///
+ /// Enable Local APIC SMI on all logical processors
+ ///
+ RunOnAllLogicalProcessors (DigitalThermalSensorEnableSmi, NULL);
+ }
+}
+
+/**
+ SMI handler to handle Digital Thermal Sensor CPU Local APIC SMI
+ for thermal threshold interrupt
+
+ @param[in] SmmImageHandle Image handle returned by the SMM driver.
+ @param[in] CommunicationBuffer Pointer to the buffer that contains the communication Message
+ @param[in] SourceSize Size of the memory image to be used for handler.
+
+ @retval EFI_SUCCESS Callback Function Executed
+**/
+EFI_STATUS
+EFIAPI
+DtsSmiCallback (
+ IN EFI_HANDLE SmmImageHandle,
+ IN OUT VOID *CommunicationBuffer,
+ IN OUT UINTN *SourceSize
+ )
+{
+ UINTN Index;
+ DTS_EVENT_TYPE EventType;
+ ///
+ /// If not enabled; return. (The DTS will be disabled upon S3 entry
+ /// and will remain disabled until after re-initialized upon wake.)
+ ///
+ if (!mDtsEnabled) {
+ return EFI_SUCCESS;
+ }
+ ///
+ /// Get the Package thermal temperature
+ ///
+ if (gIsPackageTempMsrAvailable) {
+ RunOnAllLogicalProcessors (DigitalThermalSensorEnableSmi, NULL);
+ PackageThermalDTS ();
+ } else {
+ ///
+ /// We enable the Thermal interrupt on the AP's prior to the event check
+ /// for the case where the AP has gone through the INIT-SIPI-SIPI sequence
+ /// and does not have the interrupt enabled. (This allows the AP thermal
+ /// interrupt to be re-enabled due to chipset-based SMIs without waiting
+ /// to receive a DTS event on the BSP.)
+ ///
+ for (Index = 1; Index < mSmst->NumberOfCpus; Index++) {
+ RunOnSpecificLogicalProcessor (DigitalThermalSensorEnableSmi, Index, NULL);
+ }
+ ///
+ /// Check is this a DTS SMI event or the flag of update DTS temperature and threshold value in every SMI
+ ///
+ if (DigitalThermalSensorEventCheck (&EventType) || mUpdateDtsInEverySmi) {
+ ///
+ /// Disable Local APIC SMI before programming the threshold
+ ///
+ RunOnAllLogicalProcessors (DigitalThermalSensorDisableSmi, NULL);
+
+ do {
+ ///
+ /// Handle BSP events
+ ///
+ if ((EventType == DtsEventOutOfSpec) && (mGlobalNvsAreaPtr->OperatingSystem == 0)) {
+ ///
+ /// Handle critical event by shutting down via EC if ACPI
+ /// is not enabled.
+ ///
+ PlatformEventOutOfSpec ();
+ }
+ ///
+ /// Update temperatures for PTID
+ ///
+ DigitalThermalSensorUpdatePTID ();
+
+ ///
+ /// Set the thermal trip toints as needed.
+ /// Note: We only save the highest temperature of each die in
+ /// the NVS area when more than two logical processors are
+ /// present as only the highest DTS reading is actually used by
+ /// the current ASL solution.
+ ///
+ mGlobalNvsAreaPtr->BspDigitalThermalSensorTemperature = 0;
+ mGlobalNvsAreaPtr->ApDigitalThermalSensorTemperature = 0;
+
+ ///
+ /// Set the BSP thermal sensor thresholds
+ ///
+ DigitalThermalSensorSetThreshold (&mGlobalNvsAreaPtr->BspDigitalThermalSensorTemperature);
+
+ ///
+ /// Set the AP thermal sensor thresholds and update temperatures
+ ///
+ for (Index = 1; Index < mSmst->NumberOfCpus / 2; Index++) {
+ RunOnSpecificLogicalProcessor (
+ DigitalThermalSensorSetThreshold,
+ Index,
+ &mGlobalNvsAreaPtr->BspDigitalThermalSensorTemperature
+ );
+ }
+
+ for (Index = mSmst->NumberOfCpus / 2; Index < mSmst->NumberOfCpus; Index++) {
+ RunOnSpecificLogicalProcessor (
+ DigitalThermalSensorSetThreshold,
+ Index,
+ &mGlobalNvsAreaPtr->ApDigitalThermalSensorTemperature
+ );
+ }
+ ///
+ /// Set SWGPE Status to generate an SCI if we had any events
+ ///
+ if ((EventType != DtsEventNone) || mUpdateDtsInEverySmi) {
+ DigitalThermalSensorSetSwGpeSts ();
+ }
+
+ } while (DigitalThermalSensorEventCheck (&EventType));
+ ///
+ /// Enable Local APIC SMI on all logical processors
+ ///
+ RunOnAllLogicalProcessors (DigitalThermalSensorEnableSmi, NULL);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This catches IO trap SMI generated by the ASL code to enable the DTS AP function
+
+ @param[in] DispatchHandle Not used
+ @param[in] CallbackContext Not used
+**/
+VOID
+EFIAPI
+DtsIoTrapCallback (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_IO_TRAP_DISPATCH_CALLBACK_CONTEXT *CallbackContext
+ )
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ UINT8 RetryIteration;
+
+ ///
+ /// Determine the function desired, passed in the global NVS area
+ ///
+ switch (mGlobalNvsAreaPtr->DigitalThermalSensorSmiFunction) {
+ ///
+ /// Enable AP Digital Thermal Sensor function after resume from S3
+ ///
+ case IO_TRAP_INIT_DTS_FUNCTION_AFTER_S3:
+ ///
+ /// Enable the Package DTS on the processors.
+ ///
+ if (gIsPackageTempMsrAvailable) {
+ PackageDigitalThermalSensorEnable (NULL);
+ } else {
+ ///
+ /// Enable the DTS on all logical processors.
+ ///
+ RunOnAllLogicalProcessors (DigitalThermalSensorEnable, NULL);
+ }
+
+ if (DTSSetupValue != DTS_OUT_OF_SPEC_ONLY) {
+ ///
+ /// Set the thermal trip toints on all logical processors.
+ /// Note: We only save the highest temperature of each die in the NVS area when
+ /// more than two logical processors are present as only the highest DTS reading
+ /// is actually used by the current ASL solution.
+ ///
+ mGlobalNvsAreaPtr->BspDigitalThermalSensorTemperature = 0;
+ mGlobalNvsAreaPtr->ApDigitalThermalSensorTemperature = 0;
+ mGlobalNvsAreaPtr->PackageDTSTemperature = 0;
+
+ if (gIsPackageTempMsrAvailable) {
+ PackageDigitalThermalSensorSetThreshold (&mGlobalNvsAreaPtr->PackageDTSTemperature);
+ } else {
+ ///
+ /// Update temperatures for PTID
+ ///
+ DigitalThermalSensorUpdatePTID ();
+ mGlobalNvsAreaPtr->BspDigitalThermalSensorTemperature = 0;
+ mGlobalNvsAreaPtr->ApDigitalThermalSensorTemperature = 0;
+ DigitalThermalSensorSetThreshold (&mGlobalNvsAreaPtr->BspDigitalThermalSensorTemperature);
+
+ for (Index = 1; Index < mSmst->NumberOfCpus / 2; Index++) {
+ Status = EFI_NOT_READY;
+ for (RetryIteration = 0;
+ (RetryIteration < DTS_AP_SAFE_RETRY_LIMIT) && (Status != EFI_SUCCESS);
+ RetryIteration++
+ ) {
+ Status = mSmst->SmmStartupThisAp (
+ DigitalThermalSensorSetThreshold,
+ Index,
+ &mGlobalNvsAreaPtr->BspDigitalThermalSensorTemperature
+ );
+ if (Status != EFI_SUCCESS) {
+ ///
+ /// SmmStartupThisAp might return failure if AP is busy executing some other code. Let's wait for sometime and try again.
+ ///
+ PchPmTimerStall (DTS_WAIT_PERIOD);
+ }
+ }
+ }
+
+ for (Index = mSmst->NumberOfCpus / 2; Index < mSmst->NumberOfCpus; Index++) {
+ RunOnSpecificLogicalProcessor (
+ DigitalThermalSensorSetThreshold,
+ Index,
+ &mGlobalNvsAreaPtr->ApDigitalThermalSensorTemperature
+ );
+ }
+ }
+ ///
+ /// Re-enable the DTS.
+ ///
+ mGlobalNvsAreaPtr->EnableDigitalThermalSensor = CPU_FEATURE_ENABLE;
+ } else {
+ ///
+ /// Enable Out Of Spec Interrupt
+ ///
+ if (gIsPackageTempMsrAvailable) {
+ PackageDigitalThermalSensorSetOutOfSpecInterrupt (NULL);
+ } else {
+ RunOnAllLogicalProcessors (DigitalThermalSensorSetOutOfSpecInterrupt, NULL);
+ }
+ ///
+ /// Re-enable the DTS which only handle Out-Of-Spec condition
+ ///
+ mGlobalNvsAreaPtr->EnableDigitalThermalSensor = DTS_OUT_OF_SPEC_ONLY;
+ }
+ ///
+ /// Enable the Local APIC SMI on all logical processors
+ ///
+ RunOnAllLogicalProcessors (DigitalThermalSensorEnableSmi, NULL);
+ ///
+ /// Set SWGPE Status
+ ///
+ DigitalThermalSensorSetSwGpeSts ();
+
+ mUpdateDtsInEverySmi = UPDATE_DTS_EVERY_SMI;
+ mDtsEnabled = TRUE;
+ break;
+
+ ///
+ /// Disable update DTS temperature and threshold value in every SMI
+ ///
+ case IO_TRAP_DISABLE_UPDATE_DTS:
+ mUpdateDtsInEverySmi = FALSE;
+ break;
+
+ default:
+ break;
+ }
+ ///
+ /// Store return value
+ ///
+ mGlobalNvsAreaPtr->DigitalThermalSensorSmiFunction = 0;
+}
+
+/**
+ This function executes DTS procedures for preparing to enter S3.
+
+ @param[in] Handle Handle of the callback
+ @param[in] Context The dispatch context
+
+ @retval EFI_SUCCESS DTS disabled
+**/
+VOID
+EFIAPI
+DtsS3EntryCallBack (
+ IN EFI_HANDLE Handle,
+ IN EFI_SMM_SX_DISPATCH_CONTEXT *Context
+ )
+{
+ ///
+ /// Clear the Digital Thermal Sensor flag in ACPI NVS.
+ ///
+ mGlobalNvsAreaPtr->EnableDigitalThermalSensor = CPU_FEATURE_DISABLE;
+ ///
+ /// Clear the enable flag.
+ ///
+ mDtsEnabled = FALSE;
+
+ return;
+}
+
+/**
+ Performs initialization of the threshold table.
+
+ @todo Update this function as necessary for the tables used by the implementation.
+
+ @retval EFI_SUCCESS Threshold tables initialized successfully.
+**/
+EFI_STATUS
+ThresholdTableInit (
+ VOID
+ )
+{
+ UINTN i;
+ UINT8 Delta;
+
+ ///
+ /// If the table must be updated, shift the thresholds by the difference between
+ /// TJ_MAX=110 and DtsTjMax.
+ ///
+ if (mDtsTjMax != TJ_MAX) {
+ Delta = TJ_MAX - mDtsTjMax;
+
+ for (i = 0; i < mNoOfThresholdRanges; i++) {
+ if (mDtsThresholdTable[i][1] <= mDtsTjMax) {
+ mDtsThresholdTable[i][0] = mDtsThresholdTable[i][0] - Delta;
+ } else {
+ mDtsThresholdTable[i][0] = 0;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Perform first time initialization of the Digital Thermal Sensor
+
+ @retval EFI_SUCCESS Init Digital Thermal Sensor successfully
+**/
+EFI_STATUS
+DigitalThermalSensorInit (
+ VOID
+ )
+{
+ UINTN Index;
+
+ if (DTSSetupValue != DTS_OUT_OF_SPEC_ONLY) {
+ ///
+ /// Initialize the DTS threshold table.
+ ///
+ ThresholdTableInit ();
+
+ ///
+ /// Set the thermal trip points on all logical processors.
+ /// Note: We only save the highest temperature of each die in the NVS area when
+ /// more than two logical processors are present as only the highest DTS reading
+ /// is actually used by the current ASL solution.
+ ///
+ mGlobalNvsAreaPtr->BspDigitalThermalSensorTemperature = 0;
+ mGlobalNvsAreaPtr->ApDigitalThermalSensorTemperature = 0;
+ mGlobalNvsAreaPtr->PackageDTSTemperature = 0;
+ if (gIsPackageTempMsrAvailable) {
+ PackageDigitalThermalSensorSetThreshold (&mGlobalNvsAreaPtr->PackageDTSTemperature);
+ } else {
+ ///
+ /// Update temperatures for PTID
+ ///
+ DigitalThermalSensorUpdatePTID ();
+ mGlobalNvsAreaPtr->BspDigitalThermalSensorTemperature = 0;
+ mGlobalNvsAreaPtr->ApDigitalThermalSensorTemperature = 0;
+ DigitalThermalSensorSetThreshold (&mGlobalNvsAreaPtr->BspDigitalThermalSensorTemperature);
+
+ for (Index = 1; Index < mSmst->NumberOfCpus / 2; Index++) {
+ RunOnSpecificLogicalProcessor (
+ DigitalThermalSensorSetThreshold,
+ Index,
+ &mGlobalNvsAreaPtr->BspDigitalThermalSensorTemperature
+ );
+ }
+
+ for (Index = mSmst->NumberOfCpus / 2; Index < mSmst->NumberOfCpus; Index++) {
+ RunOnSpecificLogicalProcessor (
+ DigitalThermalSensorSetThreshold,
+ Index,
+ &mGlobalNvsAreaPtr->ApDigitalThermalSensorTemperature
+ );
+ }
+ }
+
+ mGlobalNvsAreaPtr->EnableDigitalThermalSensor = CPU_FEATURE_ENABLE;
+ } else {
+ ///
+ /// Enable Out Of Spec Interrupt
+ ///
+ if (gIsPackageTempMsrAvailable) {
+ PackageDigitalThermalSensorSetOutOfSpecInterrupt (NULL);
+ } else {
+ RunOnAllLogicalProcessors (DigitalThermalSensorSetOutOfSpecInterrupt, NULL);
+ }
+
+ mGlobalNvsAreaPtr->EnableDigitalThermalSensor = DTS_OUT_OF_SPEC_ONLY;
+ }
+ ///
+ /// Enable the Local APIC SMI on all logical processors
+ ///
+ RunOnAllLogicalProcessors (DigitalThermalSensorEnableSmi, NULL);
+ ///
+ /// Set Digital Thermal Sensor flag in ACPI NVS
+ ///
+ mUpdateDtsInEverySmi = UPDATE_DTS_EVERY_SMI;
+ mDtsEnabled = TRUE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Initializes the Thermal Sensor Control MSR
+
+ This function must be AP safe.
+
+ @param[in] Buffer Unused.
+
+ @retval EFI_SUCCESS The function completed successfully.
+**/
+VOID
+EFIAPI
+DigitalThermalSensorEnable (
+ VOID *Buffer
+ )
+{
+ MSR_REGISTER MsrData;
+
+ ///
+ /// First, clear our log bits
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_IA32_THERM_STATUS);
+ if (DTSSetupValue != DTS_OUT_OF_SPEC_ONLY) {
+ MsrData.Qword &= ~THERM_STATUS_LOG_MASK;
+ } else {
+ MsrData.Qword &= ~B_OUT_OF_SPEC_STATUS_LOG;
+ }
+
+ AsmWriteMsr64 (EFI_MSR_IA32_THERM_STATUS, MsrData.Qword);
+
+ ///
+ /// Second, configure the thermal sensor control
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_MISC_PWR_MGMT);
+
+ ///
+ /// Only lock interrupts if in CMP mode
+ ///
+ if (mSmst->NumberOfCpus > 1) {
+ MsrData.Qword |= B_LOCK_THERMAL_INT;
+ }
+
+ AsmWriteMsr64 (EFI_MSR_MISC_PWR_MGMT, MsrData.Qword);
+
+ return;
+}
+
+/**
+ Initializes the Package Thermal Sensor Control MSR
+
+ @param[in] Buffer Unused.
+
+ @retval EFI_SUCCESS The function completed successfully.
+**/
+EFI_STATUS
+PackageDigitalThermalSensorEnable (
+ VOID *Buffer
+ )
+{
+ MSR_REGISTER MsrData;
+
+ ///
+ /// First, clear our log bits
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_IA32_PACKAGE_THERM_STATUS);
+ if (DTSSetupValue != DTS_OUT_OF_SPEC_ONLY) {
+ MsrData.Qword &= ~THERM_STATUS_LOG_MASK;
+ } else {
+ MsrData.Qword &= ~B_OUT_OF_SPEC_STATUS_LOG;
+ }
+
+ AsmWriteMsr64 (EFI_MSR_IA32_PACKAGE_THERM_STATUS, MsrData.Qword);
+
+ ///
+ /// Second, configure the thermal sensor control
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_MISC_PWR_MGMT);
+
+ ///
+ /// Only lock interrupts if in CMP mode
+ ///
+ if (mSmst->NumberOfCpus > 1) {
+ MsrData.Qword |= B_LOCK_THERMAL_INT;
+ }
+
+ AsmWriteMsr64 (EFI_MSR_MISC_PWR_MGMT, MsrData.Qword);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Generates a _GPE._L02 SCI to an ACPI OS.
+**/
+VOID
+DigitalThermalSensorSetSwGpeSts (
+ VOID
+ )
+{
+ UINT8 GpeCntl;
+
+ ///
+ /// Check SCI enable
+ ///
+ if (((SmmIoRead8 (mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT)) & B_PCH_ACPI_PM1_CNT_SCI_EN) != 0) {
+ ///
+ /// Do platform specific things before generate SCI
+ ///
+ PlatformHookBeforeGenerateSCI ();
+
+ ///
+ /// Set SWGPE Status
+ ///
+ GpeCntl = SmmIoRead8 (mAcpiBaseAddr + R_ACPI_GPE_CNTL);
+ GpeCntl |= B_SWGPE_CTRL;
+ SmmIoWrite8 (mAcpiBaseAddr + R_ACPI_GPE_CNTL, GpeCntl);
+ }
+}
+
+/**
+ Checks for a Core Thermal Event on any processor
+
+ @param[in] EventType - DTS_EVENT_TYPE to indicate which DTS event type has been detected.
+
+ @retval TRUE means this is a DTS Thermal event
+ @retval FALSE means this is not a DTS Thermal event.
+**/
+BOOLEAN
+DigitalThermalSensorEventCheck (
+ DTS_EVENT_TYPE *EventType
+ )
+{
+ ///
+ /// Clear event status
+ ///
+ *EventType = DtsEventNone;
+
+ RunOnAllLogicalProcessors (DigitalThermalSensorEventCheckMsr, EventType);
+ ///
+ /// Return TRUE if any logical processor reported an event.
+ ///
+ if (*EventType != DtsEventNone) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Checks for a Package Thermal Event by reading MSR.
+
+ @param[in] PkgEventType - DTS_EVENT_TYPE to indicate which DTS event type has been detected.
+
+ @retval TRUE means this is a Package DTS Thermal event
+ @retval FALSE means this is not a Package DTS Thermal event.
+**/
+BOOLEAN
+DigitalThermalSensorEventCheckPackageMsr (
+ DTS_EVENT_TYPE *PkgEventType
+ )
+{
+ MSR_REGISTER MsrData;
+
+ ///
+ /// Clear event status
+ ///
+ *PkgEventType = DtsEventNone;
+
+ ///
+ /// If Processor has already been flagged as Out-Of-Spec,
+ /// just return.
+ ///
+ if (*PkgEventType != DtsEventOutOfSpec) {
+ ///
+ /// Read thermal status
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_IA32_PACKAGE_THERM_STATUS);
+
+ ///
+ /// Check for Out-Of-Spec status.
+ ///
+ if (MsrData.Qword & B_OUT_OF_SPEC_STATUS_LOG) {
+ *PkgEventType = DtsEventOutOfSpec;
+
+ ///
+ /// Check thresholds.
+ ///
+ } else if ((DTSSetupValue != DTS_OUT_OF_SPEC_ONLY) &&
+ (MsrData.Qword & (B_THERMAL_THRESHOLD_1_STATUS_LOG | B_THERMAL_THRESHOLD_2_STATUS_LOG))
+ ) {
+ *PkgEventType = DtsEventThreshold;
+ }
+ }
+ ///
+ /// Return TRUE if processor reported an event.
+ ///
+ if (*PkgEventType != DtsEventNone) {
+ return TRUE;
+ }
+
+ return FALSE;
+
+}
+
+/**
+ Checks for a Core Thermal Event by reading MSR.
+
+ This function must be MP safe.
+
+ @param[in] Buffer Pointer to DTS_EVENT_TYPE
+**/
+VOID
+EFIAPI
+DigitalThermalSensorEventCheckMsr (
+ IN VOID *Buffer
+ )
+{
+ MSR_REGISTER MsrData;
+ DTS_EVENT_TYPE *EventType;
+
+ ///
+ /// Cast to enhance readability.
+ ///
+ EventType = (DTS_EVENT_TYPE *) Buffer;
+
+ ///
+ /// If any processor has already been flagged as Out-Of-Spec,
+ /// just return.
+ ///
+ if (*EventType != DtsEventOutOfSpec) {
+ ///
+ /// Read thermal status
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_IA32_THERM_STATUS);
+
+ ///
+ /// Check for Out-Of-Spec status.
+ ///
+ if (MsrData.Qword & B_OUT_OF_SPEC_STATUS_LOG) {
+ *EventType = DtsEventOutOfSpec;
+
+ ///
+ /// Check thresholds.
+ ///
+ } else if ((DTSSetupValue != DTS_OUT_OF_SPEC_ONLY) &&
+ (MsrData.Qword & (B_THERMAL_THRESHOLD_1_STATUS_LOG | B_THERMAL_THRESHOLD_2_STATUS_LOG))
+ ) {
+ *EventType = DtsEventThreshold;
+ }
+ }
+}
+
+/**
+ Set the Out Of Spec Interrupt in all cores
+ This function must be AP safe.
+
+ @param[in] Buffer Unused
+
+ @retval EFI_SUCCESS Out Of Spec Interrupt programmed successfully
+**/
+VOID
+EFIAPI
+DigitalThermalSensorSetOutOfSpecInterrupt (
+ VOID *Buffer
+ )
+{
+ MSR_REGISTER MsrData;
+
+ ///
+ /// Enable Out Of Spec interrupt
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_IA32_THERM_INTERRUPT);
+ MsrData.Qword |= OVERHEAT_INTERRUPT_ENABLE;
+ AsmWriteMsr64 (EFI_MSR_IA32_THERM_INTERRUPT, MsrData.Qword);
+
+ return;
+
+}
+
+/**
+ Set the Out Of Spec Interrupt on the package
+
+ @param[in] Buffer Unused
+
+ @retval EFI_SUCCESS Out Of Spec Interrupt programmed successfully
+**/
+EFI_STATUS
+PackageDigitalThermalSensorSetOutOfSpecInterrupt (
+ VOID *Buffer
+ )
+{
+ MSR_REGISTER MsrData;
+
+ ///
+ /// Enable Out Of Spec interrupt
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_IA32_PACKAGE_THERM_INTERRUPT);
+ MsrData.Qword |= OVERHEAT_INTERRUPT_ENABLE;
+ AsmWriteMsr64 (EFI_MSR_IA32_PACKAGE_THERM_INTERRUPT, MsrData.Qword);
+
+ return EFI_SUCCESS;
+
+}
+
+/**
+ Read the temperature and reconfigure the thresholds.
+ This function must be AP safe.
+
+ @param[in] Buffer Pointer to UINT8 to update with the current temperature
+
+ @retval EFI_SUCCESS Digital Thermal Sensor threshold programmed successfully
+**/
+VOID
+EFIAPI
+DigitalThermalSensorSetThreshold (
+ VOID *Buffer
+ )
+{
+ INT8 ThresholdEntry;
+ MSR_REGISTER MsrData;
+ UINT8 Temperature;
+
+ ///
+ /// Read the temperature
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_IA32_THERM_STATUS);
+
+ ///
+ /// If Out-Of-Spec, return the critical shutdown temperature.
+ ///
+ if (MsrData.Qword & B_OUT_OF_SPEC_STATUS) {
+ *((UINT8 *) Buffer) = DTS_CRITICAL_TEMPERATURE;
+ return;
+ } else if (MsrData.Qword & B_READING_VALID) {
+ ///
+ /// Find the DTS temperature.
+ ///
+ Temperature = mDtsTjMax - (MsrData.Bytes.ThirdByte & OFFSET_MASK);
+ ///
+ /// We only update the temperature if it is above the current temperature.
+ ///
+ if (Temperature > *((UINT8 *) Buffer)) {
+ *((UINT8 *) Buffer) = Temperature;
+ }
+ ///
+ /// Compare the current temperature to the Digital Thermal Sensor Threshold Table until
+ /// a matching Value is found.
+ ///
+ ThresholdEntry = 0;
+ while ((Temperature > mDtsThresholdTable[ThresholdEntry][0]) && (ThresholdEntry < (mNoOfThresholdRanges - 1))) {
+ ThresholdEntry++;
+ }
+ ///
+ /// Update the threshold values
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_IA32_THERM_INTERRUPT);
+ ///
+ /// Low temp is threshold #2
+ ///
+ MsrData.Bytes.ThirdByte = mDtsThresholdTable[ThresholdEntry][1];
+ ///
+ /// High temp is threshold #1
+ ///
+ MsrData.Bytes.SecondByte = mDtsThresholdTable[ThresholdEntry][2];
+
+ ///
+ /// Enable interrupts
+ ///
+ MsrData.Qword |= TH1_ENABLE;
+ MsrData.Qword |= TH2_ENABLE;
+
+ ///
+ /// If the high temp is at TjMax (offset == 0)
+ /// We disable the int to avoid generating a large number of SMI because of TM1/TM2
+ /// causing many threshold crossings
+ ///
+ if (MsrData.Bytes.SecondByte == 0x80) {
+ MsrData.Qword &= ~TH1_ENABLE;
+ }
+
+ AsmWriteMsr64 (EFI_MSR_IA32_THERM_INTERRUPT, MsrData.Qword);
+ }
+ ///
+ /// Clear the threshold log bits
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_IA32_THERM_STATUS);
+ MsrData.Qword &= ~THERM_STATUS_THRESHOLD_LOG_MASK;
+ AsmWriteMsr64 (EFI_MSR_IA32_THERM_STATUS, MsrData.Qword);
+
+ return;
+}
+
+/**
+ Read the temperature and reconfigure the thresholds on the package
+
+ @param[in] Buffer Pointer to UINT8 to update with the current temperature
+
+ @retval EFI_SUCCESS Digital Thermal Sensor threshold programmed successfully
+**/
+EFI_STATUS
+PackageDigitalThermalSensorSetThreshold (
+ VOID *Buffer
+ )
+{
+ INT8 ThresholdEntry;
+ MSR_REGISTER MsrData;
+ UINT8 Temperature;
+
+ ///
+ /// Read the temperature
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_IA32_PACKAGE_THERM_STATUS);
+
+ ///
+ /// If Out-Of-Spec, return the critical shutdown temperature.
+ ///
+ if (MsrData.Qword & B_OUT_OF_SPEC_STATUS) {
+ *((UINT8 *) Buffer) = DTS_CRITICAL_TEMPERATURE;
+ return EFI_SUCCESS;
+ } else if (MsrData.Qword & B_READING_VALID) {
+ ///
+ /// Update temperatures for PTID
+ ///
+ DigitalThermalSensorUpdatePTID ();
+
+ ///
+ /// Find the DTS temperature.
+ ///
+ Temperature = mDtsTjMax - (MsrData.Bytes.ThirdByte & OFFSET_MASK);
+ ///
+ /// We only update the temperature if it is above the current temperature.
+ ///
+ if (Temperature > *((UINT8 *) Buffer)) {
+ *((UINT8 *) Buffer) = Temperature;
+ }
+ ///
+ /// Compare the current temperature to the Digital Thermal Sensor Threshold Table until
+ /// a matching Value is found.
+ ///
+ ThresholdEntry = 0;
+ while ((Temperature > mDtsThresholdTable[ThresholdEntry][0]) && (ThresholdEntry < (mNoOfThresholdRanges - 1))) {
+ ThresholdEntry++;
+ }
+ ///
+ /// Update the threshold values
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_IA32_PACKAGE_THERM_INTERRUPT);
+ ///
+ /// Low temp is threshold #2
+ ///
+ MsrData.Bytes.ThirdByte = mDtsThresholdTable[ThresholdEntry][1];
+ ///
+ /// High temp is threshold #1
+ ///
+ MsrData.Bytes.SecondByte = mDtsThresholdTable[ThresholdEntry][2];
+
+ ///
+ /// Enable interrupts
+ ///
+ MsrData.Qword |= TH1_ENABLE;
+ MsrData.Qword |= TH2_ENABLE;
+
+ ///
+ /// If the high temp is at TjMax (offset == 0)
+ /// We disable the int to avoid generating a large number of SMI because of TM1/TM2
+ /// causing many threshold crossings
+ ///
+ if (MsrData.Bytes.SecondByte == 0x80) {
+ MsrData.Qword &= ~TH1_ENABLE;
+ }
+
+ AsmWriteMsr64 (EFI_MSR_IA32_PACKAGE_THERM_INTERRUPT, MsrData.Qword);
+ }
+ ///
+ /// Clear the threshold log bits
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_IA32_PACKAGE_THERM_STATUS);
+ MsrData.Qword &= ~THERM_STATUS_THRESHOLD_LOG_MASK;
+ AsmWriteMsr64 (EFI_MSR_IA32_PACKAGE_THERM_STATUS, MsrData.Qword);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Enables the Thermal Interrupt in the core Local APIC.
+
+ @param[in] Buffer Unused
+
+ @retval EFI_SUCCESS Enable Local APIC to generate a SMI successfully
+**/
+VOID
+EFIAPI
+DigitalThermalSensorEnableSmi (
+ VOID *Buffer
+ )
+{
+ UINT32 ApicThermalValue;
+ BOOLEAN x2ApicEnabled;
+
+ x2ApicEnabled = (BOOLEAN) (((AsmReadMsr64 (EFI_MSR_XAPIC_BASE)) & (BIT11 + BIT10)) == BIT11 + BIT10);
+ ///
+ /// Configure the Local APIC to generate an SMI on Thermal events. First,
+ /// Clear BIT16, BIT10-BIT8, BIT7-BIT0. Then, set BIT9 (delivery mode).
+ /// Don't enable the interrupt if it's already enabled
+ ///
+ if (x2ApicEnabled) {
+ ApicThermalValue = (UINT32) AsmReadMsr64 (EFI_MSR_EXT_XAPIC_LVT_THERM);
+ } else {
+ ApicThermalValue = *(UINT32 *) (UINTN) LOCAL_APIC_THERMAL_DEF;
+ }
+
+ if ((ApicThermalValue & (B_INTERRUPT_MASK | B_DELIVERY_MODE | B_VECTOR)) != V_MODE_SMI) {
+ ApicThermalValue = (ApicThermalValue &~(B_INTERRUPT_MASK | B_DELIVERY_MODE | B_VECTOR)) | V_MODE_SMI;
+ if (x2ApicEnabled) {
+ AsmWriteMsr64 (EFI_MSR_EXT_XAPIC_LVT_THERM, ApicThermalValue);
+ } else {
+ *(UINT32 *) (UINTN) (LOCAL_APIC_THERMAL_DEF) = (UINT32) ApicThermalValue;
+ }
+ }
+
+ return;
+}
+
+/**
+ Disables the Thermal Interrupt in the core Local APIC.
+
+ @param[in] Buffer Unused
+
+ @retval EFI_SUCCESS Disable Local APIC to generate a SMI successfully
+**/
+VOID
+EFIAPI
+DigitalThermalSensorDisableSmi (
+ VOID *Buffer
+ )
+{
+ UINT32 ApicThermalValue;
+ BOOLEAN x2ApicEnabled;
+
+ x2ApicEnabled = (BOOLEAN) (((AsmReadMsr64 (EFI_MSR_XAPIC_BASE)) & (BIT11 + BIT10)) == BIT11 + BIT10);
+ ///
+ /// Disable Local APIC thermal entry
+ ///
+ if (x2ApicEnabled) {
+ ApicThermalValue = (UINT32) AsmReadMsr64 (EFI_MSR_EXT_XAPIC_LVT_THERM);
+ } else {
+ ApicThermalValue = *(UINT32 *) (UINTN) LOCAL_APIC_THERMAL_DEF;
+ }
+ ///
+ /// Following descriptions were from SSE BIOS
+ /// We set the interrupt mode at the same time as the interrupt is disabled to
+ /// avoid the "Received Illegal Vector" being set in the Error Status Register.
+ /// and eax, 0FFFEF800h
+ /// or eax, 000010200h ; Clear Mask, Set Delivery
+ ///
+ ApicThermalValue = (ApicThermalValue &~(B_INTERRUPT_MASK | B_DELIVERY_MODE | B_VECTOR)) | (B_INTERRUPT_MASK | V_MODE_SMI);
+ if (x2ApicEnabled) {
+ AsmWriteMsr64 (EFI_MSR_EXT_XAPIC_LVT_THERM, ApicThermalValue);
+ } else {
+ *(UINT32 *) (UINTN) (LOCAL_APIC_THERMAL_DEF) = (UINT32) ApicThermalValue;
+ }
+
+ return;
+}
+
+/**
+ Runs the specified procedure on all logical processors, passing in the
+ parameter buffer to the procedure.
+
+ @param[in] Procedure The function to be run.
+ @param[in] Buffer Pointer to a parameter buffer.
+
+ @retval EFI_SUCCESS Function executed successfully.
+**/
+STATIC
+EFI_STATUS
+RunOnAllLogicalProcessors (
+ IN OUT EFI_AP_PROCEDURE Procedure,
+ IN OUT VOID *Buffer
+ )
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ UINT8 RetryIteration;
+ ///
+ /// Run the procedure on all logical processors.
+ ///
+ for (Index = 1; Index < mSmst->NumberOfCpus; Index++) {
+ Status = EFI_NOT_READY;
+ for (RetryIteration = 0; (RetryIteration < DTS_AP_SAFE_RETRY_LIMIT) && (Status != EFI_SUCCESS); RetryIteration++) {
+ Status = mSmst->SmmStartupThisAp (Procedure, Index, Buffer);
+ if (Status != EFI_SUCCESS) {
+ ///
+ /// SmmStartupThisAp might return failure if AP is busy executing some other code. Let's wait for sometime and try again.
+ ///
+ PchPmTimerStall (DTS_WAIT_PERIOD);
+ }
+ }
+ }
+ PchPmTimerStall (DTS_WAIT_PERIOD);
+ (*Procedure)(Buffer);
+ return EFI_SUCCESS;
+}
+
+/**
+ Runs the specified procedure on one specific logical processors, passing in the
+ parameter buffer to the procedure.
+
+ @param[in] Procedure The function to be run.
+ @param[in] Index Indicate which logical processor should execute this procedure
+ @param[in] Buffer Pointer to a parameter buffer.
+
+ @retval EFI_SUCCESS Function executed successfully.
+**/
+STATIC
+EFI_STATUS
+RunOnSpecificLogicalProcessor (
+ IN OUT EFI_AP_PROCEDURE Procedure,
+ IN UINTN Index,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 RetryIteration;
+ ///
+ /// Run the procedure on one specific logical processor.
+ ///
+ Status = EFI_NOT_READY;
+ for (RetryIteration = 0; (RetryIteration < DTS_AP_SAFE_RETRY_LIMIT) && (Status != EFI_SUCCESS); RetryIteration++) {
+ Status = mSmst->SmmStartupThisAp (Procedure, Index, Buffer);
+ if (Status != EFI_SUCCESS) {
+ ///
+ /// SmmStartupThisAp might return failure if AP is busy executing some other code. Let's wait for sometime and try again.
+ ///
+ PchPmTimerStall (DTS_WAIT_PERIOD);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Digital Thermal Sensor (DTS) SMM driver entry point function.
+
+ @param[in] ImageHandle Image handle for this driver image
+ @param[in] SystemTable Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS Driver initialization completed successfully
+ @retval EFI_OUT_OF_RESOURCES Error when allocating required memory buffer.
+**/
+EFI_STATUS
+InstallDigitalThermalSensor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+ MSR_REGISTER MsrData;
+ EFI_GLOBAL_NVS_AREA_PROTOCOL *GlobalNvsAreaProtocol;
+ EFI_SMM_SX_DISPATCH_CONTEXT SxDispatchContext;
+ EFI_SMM_SX_DISPATCH_PROTOCOL *SxDispatchProtocol;
+ EFI_HANDLE SxDispatchHandle;
+
+ EFI_SMM_IO_TRAP_DISPATCH_PROTOCOL *PchIoTrap;
+ EFI_HANDLE PchIoTrapHandle;
+ EFI_SMM_IO_TRAP_DISPATCH_REGISTER_CONTEXT PchIoTrapContext;
+ EFI_CPUID_REGISTER Cpuid06;
+
+ ///
+ /// Install DTS_INIT_STATUS_PROTOCOL protocol
+ ///
+ Handle = NULL;
+ mDtsInitStatusProtocol.IsDtsInitComplete = FALSE;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gDtsInitStatusProtocolGuid,
+ &mDtsInitStatusProtocol,
+ NULL
+ );
+
+ ///
+ /// Locate DTS platform policy.
+ ///
+ Status = gBS->LocateProtocol (
+ &gDxeCpuPlatformPolicyProtocolGuid,
+ NULL,
+ (VOID **) &mPlatformCpu
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "No DTS Platform Policy Protocol available"));
+ }
+
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Check if DTS disabled in setup.
+ ///
+ if (mPlatformCpu->CpuConfig->EnableDts == CPU_FEATURE_DISABLE) {
+ DEBUG ((EFI_D_WARN, "DTS not enabled/supported, so driver not loaded into SMM\n"));
+ return EFI_SUCCESS;
+ }
+ ///
+ /// Find the SMM base protocol
+ ///
+ Status = gBS->LocateProtocol (&gEfiSmmBaseProtocolGuid, NULL, (VOID **) &mSmmBase);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Initialize global variables.
+ ///
+ Status = mSmmBase->GetSmstLocation (mSmmBase, &mSmst);
+ ASSERT_EFI_ERROR (Status);
+ ///
+ /// Verify the code supports the number of processors present.
+ ///
+ ASSERT (mSmst->NumberOfCpus <= MAX_NUMBER_OF_THREADS_SUPPORTED);
+
+ ///
+ /// Get the ACPI Base Address
+ ///
+ mAcpiBaseAddr = MmioRead16 (MmPciExpressAddress (0, PCI_DEVICE_NUMBER_PCH_LPC, 0, R_PCH_LPC_ACPI_BASE)) &~BIT0;
+
+ ///
+ /// Initialize DTS setup value
+ ///
+ DTSSetupValue = mPlatformCpu->CpuConfig->EnableDts;
+
+ ///
+ /// Locate our shared data area
+ ///
+ Status = gBS->LocateProtocol (&mEfiGlobalNvsAreaProtocolGuid, NULL, (VOID **) &GlobalNvsAreaProtocol);
+ ASSERT_EFI_ERROR (Status);
+ mGlobalNvsAreaPtr = GlobalNvsAreaProtocol->Area;
+ ///
+ /// CPU_ID 6, EAX bit 6 for the Package temperature MSR support
+ ///
+ ZeroMem (&Cpuid06, sizeof (Cpuid06));
+ AsmCpuid (6, &Cpuid06.RegEax, &Cpuid06.RegEbx, &Cpuid06.RegEcx, &Cpuid06.RegEdx);
+
+ gIsPackageTempMsrAvailable = (BOOLEAN) ((Cpuid06.RegEax >> 6) & 0x01);
+ mGlobalNvsAreaPtr->IsPackageTempMSRAvailable = gIsPackageTempMsrAvailable;
+ ///
+ /// Locate Platform specific data area, or prepare platform services
+ ///
+ InitializeDtsHookLib ();
+
+ ///
+ /// Initialize ASL manipulation library
+ ///
+ InitializeAslUpdateLib ();
+
+ ///
+ /// Locate the PCH Trap dispatch protocol
+ ///
+ Status = gBS->LocateProtocol (&mEfiSmmIoTrapDispatchProtocolGuid, NULL, (VOID **) &PchIoTrap);
+ ASSERT_EFI_ERROR (Status);
+
+ PchIoTrapContext.Type = ReadWriteTrap;
+ PchIoTrapContext.Length = 4;
+ PchIoTrapContext.Address = 0;
+ PchIoTrapContext.Context = NULL;
+ PchIoTrapContext.MergeDisable = FALSE;
+ Status = PchIoTrap->Register (
+ PchIoTrap,
+ DtsIoTrapCallback,
+ &PchIoTrapContext,
+ &PchIoTrapHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Update two ASL items.
+ /// 1: Operating Region for DTS IO Trap.
+ /// 2: Resource Consumption in LPC Device.
+ ///
+ ASSERT (PchIoTrapContext.Length <= (UINT8) (-1));
+ Status = UpdateAslCode (
+ (EFI_SIGNATURE_32 ('I', 'O', '_', 'D')),
+ PchIoTrapContext.Address,
+ (UINT8) PchIoTrapContext.Length
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Register a callback function to handle Digital Thermal Sensor SMIs.
+ ///
+ if (mPlatformCpu->CpuConfig->EnableDts != DTS_OUT_OF_SPEC_ONLY) {
+ Status = mSmmBase->RegisterCallback (mSmmBase, ImageHandle, DtsSmiCallback, FALSE, FALSE);
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ Status = mSmmBase->RegisterCallback (mSmmBase, ImageHandle, DtsOutOfSpecSmiCallback, FALSE, FALSE);
+ ASSERT_EFI_ERROR (Status);
+ }
+ ///
+ /// Locate the Sx Dispatch Protocol
+ ///
+ Status = gBS->LocateProtocol (
+ &gEfiSmmSxDispatchProtocolGuid,
+ NULL,
+ (VOID **) &SxDispatchProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Register the callback for S3 entry
+ ///
+ SxDispatchContext.Type = SxS3;
+ SxDispatchContext.Phase = SxEntry;
+ Status = SxDispatchProtocol->Register (
+ SxDispatchProtocol,
+ DtsS3EntryCallBack,
+ &SxDispatchContext,
+ &SxDispatchHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (mPlatformCpu->CpuConfig->EnableDts != DTS_OUT_OF_SPEC_ONLY) {
+ ///
+ /// Get the TCC Activation Temperature and use it for TjMax.
+ ///
+ MsrData.Qword = AsmReadMsr64 (EFI_MSR_IA32_TEMPERATURE_TARGET);
+
+ mDtsTjMax = (MsrData.Bytes.ThirdByte);
+ mDtsThresholdTable = mDigitalThermalSensorThresholdTable;
+ mNoOfThresholdRanges = DTS_NUMBER_THRESHOLD_RANGES;
+ }
+
+ if (gIsPackageTempMsrAvailable) {
+ ///
+ /// Enable the DTS on package.
+ ///
+ PackageDigitalThermalSensorEnable (NULL);
+ } else {
+ ///
+ /// Enable the DTS on all logical processors.
+ ///
+ RunOnAllLogicalProcessors (DigitalThermalSensorEnable, NULL);
+ }
+ ///
+ /// Initialize Digital Thermal Sensor Function in POST
+ ///
+ DigitalThermalSensorInit ();
+
+ mDtsInitStatusProtocol.IsDtsInitComplete = TRUE;
+
+ return EFI_SUCCESS;
+}
diff --git a/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.cif b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.cif
new file mode 100644
index 0000000..c0b71a1
--- /dev/null
+++ b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.cif
@@ -0,0 +1,15 @@
+<component>
+ name = "DigitalThermalSensorSmm"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\DTS\Smm"
+ RefName = "DigitalThermalSensorSmm"
+[files]
+"DigitalThermalSensorSmm.mak"
+"DigitalThermalSensorSmm.sdl"
+"DigitalThermalSensorSmm.inf"
+"DigitalThermalSensorSmm.c"
+"DigitalThermalSensorSmm.dxs"
+"DigitalThermalSensorSmm.h"
+"DigitalThermalSensorInitStatus.h"
+"DigitalThermalSensorLib.h"
+<endComponent>
diff --git a/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.dxs b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.dxs
new file mode 100644
index 0000000..cc37eff
--- /dev/null
+++ b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.dxs
@@ -0,0 +1,52 @@
+/** @file
+
+ Dispatch dependency expression file for the DigitalThermalSensorSmm driver.
+
+@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 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
+
+**/
+
+
+#include "AutoGen.h"
+#include "DxeDepex.h"
+
+//
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are both "defined" in R8 codebase;
+// BUILD_WITH_EDKII_GLUE_LIB is defined in Edk-Dev-Snapshot-20070228 and later version
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are "not defined" in R9 codebase.
+//
+#if defined (BUILD_WITH_GLUELIB) || defined (BUILD_WITH_EDKII_GLUE_LIB)
+#include "EfiDepex.h"
+#endif
+
+#include EFI_PROTOCOL_DEPENDENCY (AcpiSupport)
+#include EFI_PROTOCOL_DEPENDENCY (SmmBase)
+#include EFI_PROTOCOL_DEPENDENCY (GlobalNvsArea)
+#include EFI_PROTOCOL_DEFINITION (SmmIoTrapDispatch)
+#include EFI_PROTOCOL_DEPENDENCY (SmmSxDispatch)
+#include EFI_PROTOCOL_DEPENDENCY (CpuPlatformPolicy)
+
+DEPENDENCY_START
+ EFI_ACPI_SUPPORT_GUID AND
+ EFI_SMM_BASE_PROTOCOL_GUID AND
+ EFI_SMM_IO_TRAP_DISPATCH_PROTOCOL_GUID AND
+ EFI_GLOBAL_NVS_AREA_PROTOCOL_GUID AND
+ EFI_SMM_SX_DISPATCH_PROTOCOL_GUID AND
+ DXE_CPU_PLATFORM_POLICY_PROTOCOL_GUID
+DEPENDENCY_END
+
diff --git a/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.h b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.h
new file mode 100644
index 0000000..f89e982
--- /dev/null
+++ b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.h
@@ -0,0 +1,477 @@
+/** @file
+ Defines and prototypes for the Digital Thermal Sensor SMM driver
+
+@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 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
+
+**/
+#ifndef _DIGITAL_THERMAL_SENSOR_SMM_H_
+#define _DIGITAL_THERMAL_SENSOR_SMM_H_
+
+//
+// Include files
+//
+#include "EdkIIGlueDxe.h"
+#include "CpuFuncs.h"
+#include "Cpu.h"
+
+//
+// Include dependent protocols
+//
+#include EFI_PROTOCOL_DEPENDENCY (LoadedImage)
+#include EFI_PROTOCOL_DEPENDENCY (SmmBase)
+#include EFI_PROTOCOL_DEPENDENCY (GlobalNvsArea)
+#include EFI_PROTOCOL_DEPENDENCY (SmmIchnDispatch)
+#include EFI_PROTOCOL_DEPENDENCY (SmmIoTrapDispatch)
+#include EFI_PROTOCOL_DEPENDENCY (SmmSxDispatch)
+#include EFI_PROTOCOL_DEFINITION (CpuPlatformPolicy)
+
+#include "SmmIoLib.h"
+#include "AslUpdateLib.h"
+#include "DigitalThermalSensorlib.h"
+
+#include "DigitalThermalSensorInitStatus.h"
+#include "CpuRegs.h"
+#include "PchAccess.h"
+#include "PchPlatformLib.h"
+
+///
+/// Stall period in microseconds
+///
+#define DTS_WAIT_PERIOD 1
+#define DTS_AP_SAFE_RETRY_LIMIT 3
+///
+/// Define module definitions
+///
+#define TJ_MAX 110
+#define DTS_CRITICAL_TEMPERATURE 255
+
+#define DTS_SAMPLE_RATE 0x10
+#define EFI_MSR_XAPIC_BASE 0x1B
+#define EFI_MSR_IA32_THERM_INTERRUPT 0x19B
+#define TH1_VALUE 8
+#define TH1_ENABLE (1 << 15)
+#define TH2_VALUE 16
+#define TH2_ENABLE (1 << 23)
+#define OFFSET_MASK (0x7F)
+#define OVERHEAT_INTERRUPT_ENABLE (1 << 4)
+
+#define B_OUT_OF_SPEC_STATUS (1 << 4)
+#define B_OUT_OF_SPEC_STATUS_LOG (1 << 5)
+#define B_THERMAL_THRESHOLD_1_STATUS (1 << 6)
+#define B_THERMAL_THRESHOLD_1_STATUS_LOG (1 << 7)
+#define B_THERMAL_THRESHOLD_2_STATUS (1 << 8)
+#define B_THERMAL_THRESHOLD_2_STATUS_LOG (1 << 9)
+#define B_READING_VALID (1 << 31)
+
+#define EFI_MSR_IA32_TEMPERATURE_TARGET 0x1A2
+#define EFI_MSR_EXT_XAPIC_LVT_THERM 0x833
+#define EFI_MSR_MISC_PWR_MGMT 0x1AA
+#define B_LOCK_THERMAL_INT (1 << 22)
+
+#define THERM_STATUS_LOG_MASK (B_THERMAL_THRESHOLD_2_STATUS_LOG | B_THERMAL_THRESHOLD_1_STATUS_LOG | B_OUT_OF_SPEC_STATUS_LOG)
+#define THERM_STATUS_THRESHOLD_LOG_MASK (B_THERMAL_THRESHOLD_2_STATUS_LOG | B_THERMAL_THRESHOLD_1_STATUS_LOG)
+
+#define EFI_MSR_IA32_PACKAGE_THERM_STATUS 0x1B1
+#define EFI_MSR_IA32_PACKAGE_THERM_INTERRUPT 0x1B2
+
+#define B_DTS_IO_TRAP (1 << 2)
+#define R_ACPI_GPE_CNTL 0x42 ///< ACPI PM IO register 42h
+#define R_ACPI_SMI_EN 0x30 ///< ACPI PM IO register 30h
+#define B_SWGPE_CTRL (1 << 1)
+#define DTS_IO_TRAP_REGISTER_LOW_DWORD (0x00040001 + ICH_DTS_IO_TRAP_BASE_ADDRESS) ///< DigitalThermalSensor IO Trap High DWord value
+#define DTS_IO_TRAP_REGISTER_HIGH_DWORD 0x000200F0 ///< DigitalThermalSensor IO Trap High DWord value
+#define LOCAL_APIC_THERMAL_DEF 0xFEE00330
+#define B_INTERRUPT_MASK (1 << 16)
+#define B_DELIVERY_MODE (0x07 << 8)
+#define V_MODE_SMI (0x02 << 8)
+#define B_VECTOR (0xFF << 0)
+
+#define DTS_NUMBER_THRESHOLD_RANGES 9 ///< How many ranges are in the threshold table
+#define IO_TRAP_INIT_AP_DTS_FUNCTION 0x0A ///< Enable AP DigitalThermalSensor function
+#define IO_TRAP_INIT_DTS_FUNCTION_AFTER_S3 0x14 ///< Enable Digital Thermal Sensor function after resume from S3
+#define IO_TRAP_DISABLE_UPDATE_DTS 0x1E ///< Disable update DTS temperature and threshold value in every SMI
+#define INIT_DTS_SCF_MIN 0x10 ///< SCF Minimum value.
+#define INIT_DTS_SCF_UNITY 0x20 ///< SCF Unity Value.
+#define INIT_DTS_SCF_MAX 0x30 ///< SCF Maximum value.
+#define UPDATE_DTS_EVERY_SMI TRUE ///< Update DTS temperature and threshold value in every SMI
+#define R_PCH_ACPI_PM1_CNT 0x04
+#define B_PCH_ACPI_PM1_CNT_SCI_EN 0x00000001
+#define R_PCH_LPC_ACPI_BASE 0x40
+#define PCI_DEVICE_NUMBER_PCH_LPC 31
+#define MAX_NUMBER_OF_THREADS_SUPPORTED 8 ///< Max number of threads supported by processor.
+#ifndef BIT63
+#define BIT0 0x0001
+#define BIT1 0x0002
+#define BIT2 0x0004
+#define BIT3 0x0008
+#define BIT4 0x0010
+#define BIT5 0x0020
+#define BIT6 0x0040
+#define BIT7 0x0080
+#define BIT8 0x0100
+#define BIT9 0x0200
+#define BIT10 0x0400
+#define BIT11 0x0800
+#define BIT12 0x1000
+#define BIT13 0x2000
+#define BIT14 0x4000
+#define BIT15 0x8000
+#define BIT16 0x00010000
+#define BIT17 0x00020000
+#define BIT18 0x00040000
+#define BIT19 0x00080000
+#define BIT20 0x00100000
+#define BIT21 0x00200000
+#define BIT22 0x00400000
+#define BIT23 0x00800000
+#define BIT24 0x01000000
+#define BIT25 0x02000000
+#define BIT26 0x04000000
+#define BIT27 0x08000000
+#define BIT28 0x10000000
+#define BIT29 0x20000000
+#define BIT30 0x40000000
+#define BIT31 0x80000000
+#define BIT32 0x100000000
+#define BIT33 0x200000000
+#define BIT34 0x400000000
+#define BIT35 0x800000000
+#define BIT36 0x1000000000
+#define BIT37 0x2000000000
+#define BIT38 0x4000000000
+#define BIT39 0x8000000000
+#define BIT40 0x10000000000
+#define BIT41 0x20000000000
+#define BIT42 0x40000000000
+#define BIT43 0x80000000000
+#define BIT44 0x100000000000
+#define BIT45 0x200000000000
+#define BIT46 0x400000000000
+#define BIT47 0x800000000000
+#define BIT48 0x1000000000000
+#define BIT49 0x2000000000000
+#define BIT50 0x4000000000000
+#define BIT51 0x8000000000000
+#define BIT52 0x10000000000000
+#define BIT53 0x20000000000000
+#define BIT54 0x40000000000000
+#define BIT55 0x80000000000000
+#define BIT56 0x100000000000000
+#define BIT57 0x200000000000000
+#define BIT58 0x400000000000000
+#define BIT59 0x800000000000000
+#define BIT60 0x1000000000000000
+#define BIT61 0x2000000000000000
+#define BIT62 0x4000000000000000
+#define BIT63 0x8000000000000000
+#endif
+///
+/// Enumerate a DTS event type
+///
+typedef enum {
+ DtsEventNone,
+ DtsEventThreshold,
+ DtsEventOutOfSpec,
+ DtsEventMax
+} DTS_EVENT_TYPE;
+
+///
+/// Memory Mapped PCI Access macro
+///
+//#define MmPciExpressAddress(Bus, Device, Function, Register) \
+// ( \
+// (UINTN) GetPciExpressBaseAddress () + (UINTN) (Bus << 20) + (UINTN) (Device << 15) + (UINTN) \
+// (Function << 12) + (UINTN) (Register) \
+// )
+
+#define MmPciExpressAddress(Bus, Device, Function, Register) \
+ ( \
+ (UINTN) PlatformPciExpressBaseAddress + (UINTN) (Bus << 20) + (UINTN) (Device << 15) + (UINTN) \
+ (Function << 12) + (UINTN) (Register) \
+ )
+
+//
+// Function declarations
+//
+/**
+ SMI handler to handle Digital Thermal Sensor CPU Local APIC SMI
+ for thermal threshold interrupt
+
+ @param[in] SmmImageHandle Image handle returned by the SMM driver.
+ @param[in] CommunicationBuffer Pointer to the buffer that contains the communication Message
+ @param[in] SourceSize Size of the memory image to be used for handler.
+
+ @retval EFI_SUCCESS Callback Function Executed
+**/
+EFI_STATUS
+EFIAPI
+DtsSmiCallback (
+ IN EFI_HANDLE SmmImageHandle,
+ IN OUT VOID *CommunicationBuffer,
+ IN OUT UINTN *SourceSize
+ );
+
+/**
+ Call from SMI handler to handle Package thermal temperature Digital Thermal Sensor CPU Local APIC SMI
+ for thermal threshold interrupt
+
+ @retval None
+**/
+VOID
+PackageThermalDTS (
+ VOID
+ );
+
+/**
+ Perform first time initialization of the Digital Thermal Sensor
+
+ @retval EFI_SUCCESS Init Digital Thermal Sensor successfully
+**/
+EFI_STATUS
+DigitalThermalSensorInit (
+ VOID
+ );
+
+/**
+ Initializes the Thermal Sensor Control MSR
+
+ This function must be AP safe.
+
+ @param[in] Buffer Unused.
+
+ @retval EFI_SUCCESS The function completed successfully.
+**/
+VOID
+EFIAPI
+DigitalThermalSensorEnable (
+ VOID *Buffer
+ );
+
+/**
+ Initializes the Package Thermal Sensor Control MSR
+
+ @param[in] Buffer Unused.
+
+ @retval EFI_SUCCESS The function completed successfully.
+**/
+EFI_STATUS
+PackageDigitalThermalSensorEnable (
+ VOID *Buffer
+ );
+
+/**
+ Generates a _GPE._L02 SCI to an ACPI OS.
+**/
+VOID
+DigitalThermalSensorSetSwGpeSts (
+ VOID
+ );
+
+/**
+ Checks for a Core Thermal Event by reading MSR.
+
+ This function must be MP safe.
+
+ @param[in] Buffer Pointer to DTS_EVENT_TYPE
+**/
+VOID
+EFIAPI
+DigitalThermalSensorEventCheckMsr (
+ IN VOID *Buffer
+ );
+
+/**
+ Checks for a Package Thermal Event by reading MSR.
+
+ @param[in] PkgEventType - DTS_EVENT_TYPE to indicate which DTS event type has been detected.
+
+ @retval TRUE means this is a Package DTS Thermal event
+ @retval FALSE means this is not a Package DTS Thermal event.
+**/
+BOOLEAN
+DigitalThermalSensorEventCheckPackageMsr (
+ DTS_EVENT_TYPE *PkgEventType
+ );
+
+/**
+ Checks for a Core Thermal Event on any processor
+
+ @param[in] EventType - DTS_EVENT_TYPE to indicate which DTS event type has been detected.
+
+ @retval TRUE means this is a DTS Thermal event
+ @retval FALSE means this is not a DTS Thermal event.
+**/
+BOOLEAN
+DigitalThermalSensorEventCheck (
+ DTS_EVENT_TYPE *EventType
+ );
+
+/**
+ Read the temperature and reconfigure the thresholds.
+ This function must be AP safe.
+
+ @param[in] Buffer Pointer to UINT8 to update with the current temperature
+
+ @retval EFI_SUCCESS Digital Thermal Sensor threshold programmed successfully
+**/
+VOID
+EFIAPI
+DigitalThermalSensorSetThreshold (
+ VOID *Buffer
+ );
+
+/**
+ Read the temperature and reconfigure the thresholds on the package
+
+ @param[in] Buffer Pointer to UINT8 to update with the current temperature
+
+ @retval EFI_SUCCESS Digital Thermal Sensor threshold programmed successfully
+**/
+EFI_STATUS
+PackageDigitalThermalSensorSetThreshold (
+ VOID *Buffer
+ );
+
+/**
+ Set the Out Of Spec Interrupt in all cores
+ This function must be AP safe.
+
+ @param[in] Buffer Unused
+
+ @retval EFI_SUCCESS Out Of Spec Interrupt programmed successfully
+**/
+VOID
+EFIAPI
+DigitalThermalSensorSetOutOfSpecInterrupt (
+ VOID *Buffer
+ );
+
+/**
+ Set the Out Of Spec Interrupt on the package
+
+ @param[in] Buffer Unused
+
+ @retval EFI_SUCCESS Out Of Spec Interrupt programmed successfully
+**/
+EFI_STATUS
+PackageDigitalThermalSensorSetOutOfSpecInterrupt (
+ VOID *Buffer
+ );
+
+/**
+ Enables the Thermal Interrupt in the core Local APIC.
+
+ @param[in] Buffer Unused
+
+ @retval EFI_SUCCESS Enable Local APIC to generate a SMI successfully
+**/
+VOID
+EFIAPI
+DigitalThermalSensorEnableSmi (
+ VOID *Buffer
+ );
+
+/**
+ Disables the Thermal Interrupt in the core Local APIC.
+
+ @param[in] Buffer Unused
+
+ @retval EFI_SUCCESS Disable Local APIC to generate a SMI successfully
+**/
+VOID
+EFIAPI
+DigitalThermalSensorDisableSmi (
+ VOID *Buffer
+ );
+
+/**
+ Digital Thermal Sensor (DTS) SMM driver entry point function.
+
+ @param[in] ImageHandle Image handle for this driver image
+ @param[in] SystemTable Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS Driver initialization completed successfully
+**/
+EFI_STATUS
+InstallDigitalThermalSensor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Runs the specified procedure on all logical processors, passing in the
+ parameter buffer to the procedure.
+
+ @param[in] Procedure The function to be run.
+ @param[in] Buffer Pointer to a parameter buffer.
+
+ @retval EFI_SUCCESS Function executed successfully.
+**/
+STATIC
+EFI_STATUS
+RunOnAllLogicalProcessors (
+ IN OUT EFI_AP_PROCEDURE Procedure,
+ IN OUT VOID *Buffer
+ );
+
+/**
+ Runs the specified procedure on one specific logical processors, passing in the
+ parameter buffer to the procedure.
+
+ @param[in] Procedure The function to be run.
+ @param[in] Index Indicate which logical processor should execute this procedure
+ @param[in] Buffer Pointer to a parameter buffer.
+
+ @retval EFI_SUCCESS Function executed successfully.
+**/
+STATIC
+EFI_STATUS
+RunOnSpecificLogicalProcessor (
+ IN OUT EFI_AP_PROCEDURE Procedure,
+ IN UINTN Index,
+ IN OUT VOID *Buffer
+ );
+
+/**
+ Performs initialization of the threshold table.
+
+ @todo Update this function as necessary for the tables used by the implementation.
+
+ @retval EFI_SUCCESS Threshold tables initialized successfully.
+**/
+EFI_STATUS
+ThresholdTableInit (
+ VOID
+ );
+
+/**
+ This function executes DTS procedures for preparing to enter S3.
+
+ @param[in] Handle Handle of the callback
+ @param[in] Context The dispatch context
+
+ @retval EFI_SUCCESS DTS disabled
+**/
+VOID
+EFIAPI
+DtsS3EntryCallBack (
+ IN EFI_HANDLE Handle,
+ IN EFI_SMM_SX_DISPATCH_CONTEXT *Context
+ );
+
+#endif
diff --git a/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.inf b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.inf
new file mode 100644
index 0000000..f5d0d57
--- /dev/null
+++ b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.inf
@@ -0,0 +1,106 @@
+## @file
+# Component description file for the DigitalThermalSensor SMM driver
+#
+#@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 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
+#
+
+
+[defines]
+BASE_NAME = DigitalThermalSensorSmm
+FILE_GUID = 77A6009E-116E-464D-8EF8-B35201A022DD
+COMPONENT_TYPE = RT_DRIVER
+
+[sources.common]
+ DigitalThermalSensorSmm.c
+ DigitalThermalSensorSmm.h
+
+#
+# Edk II Glue Driver Entry Point
+#
+ EdkIIGlueSmmDriverEntryPoint.c
+
+[includes.common]
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Framework
+ .
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Core/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include/Pcd
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include/Library
+ $(EDK_SOURCE)/Foundation/Cpu/Pentium/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Samplecode
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Samplecode/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Samplecode/Library/AslUpdate/Dxe
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library
+ $(EFI_SOURCE)
+
+
+[includes.ipf]
+
+[libraries.common]
+ EdkProtocolLib
+ ArchProtocolLib
+ EdkFrameworkProtocolLib
+ EdkIIGlueBaseLib
+ EdkIIGlueBaseIoLibIntrinsic
+ EdkIIGlueBaseMemoryLib
+ EdkIIGlueDxeMemoryAllocationLib
+ EdkIIGlueSmmRuntimeDxeReportStatusCodeLib
+ EdkIIGlueUefiLib
+ EdkIIGlueUefiBootServicesTableLib
+ EdkIIGlueUefiRuntimeServicesTableLib
+ EdkIIGlueDxeDebugLibReportStatusCode
+ EdkIIGlueUefiDevicePathLib
+ EdkIIGlueBasePciLibPciExpress
+ EdkIIGlueBasePciExpressLib
+ EfiProtocolLib
+ DTSHookLib
+ DxeAslUpdateLib
+ SmmIoLib
+ SmmKscLib
+ CpuProtocolLib
+ PchPlatformLib
+
+[nmake.common]
+ IMAGE_ENTRY_POINT=_ModuleEntryPoint
+ DPX_SOURCE=DigitalThermalSensorSmm.dxs
+
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=InstallDigitalThermalSensor
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_BASE_LIB__ \
+ -D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ -D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ -D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \
+ -D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ -D __EDKII_GLUE_SMM_RUNTIME_DXE_REPORT_STATUS_CODE_LIB__ \
+ -D __EDKII_GLUE_UEFI_LIB__\
+ -D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_UEFI_DEVICE_PATH_LIB__ \
+ -D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__
+
diff --git a/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.mak b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.mak
new file mode 100644
index 0000000..a1386d5
--- /dev/null
+++ b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.mak
@@ -0,0 +1,77 @@
+# MAK file for the Module Part: PowerMgmtS3
+
+EDK : DigitalThermalSensorSmm
+
+BUILD_DigitalThermalSensorSmm_DIR = $(BUILD_DIR)\$(DigitalThermalSensorSmm_DIR)
+
+$(BUILD_DIR)\DigitalThermalSensorSmm.mak : $(DigitalThermalSensorSmm_DIR)\DigitalThermalSensorSmm.cif $(BUILD_RULES)
+ $(CIF2MAK) $(DigitalThermalSensorSmm_DIR)\DigitalThermalSensorSmm.cif $(CIF2MAK_DEFAULTS)
+
+DigitalThermalSensorSmm : $(BUILD_DIR)\DigitalThermalSensorSmm.mak DigitalThermalSensorSmmBin
+
+DigitalThermalSensorSmm_OBJECTS = \
+ $(BUILD_DigitalThermalSensorSmm_DIR)\DigitalThermalSensorSmm.obj
+
+DigitalThermalSensorSmm_MY_INCLUDES= \
+ $(EDK_INCLUDES) \
+ $(PROJECT_CPU_INCLUDES)\
+ $(INTEL_PLATFORM_PROTOCOL_INCLUDES)\
+ $(INTEL_PCH_INCLUDES)\
+ $(INTEL_MCH_INCLUDES)
+
+DigitalThermalSensorSmm_DEFINES = $(MY_DEFINES)\
+ /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=InstallDigitalThermalSensor"\
+ /D PlatformPciExpressBaseAddress=$(PCIEX_BASE_ADDRESS) \
+ /D __EDKII_GLUE_BASE_LIB__ \
+ /D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ /D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ /D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \
+ /D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \
+ /D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ /D __EDKII_GLUE_SMM_RUNTIME_DXE_REPORT_STATUS_CODE_LIB__ \
+ /D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \
+# /D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ \
+ /D __EDKII_GLUE_UEFI_DEVICE_PATH_LIB__
+
+DigitalThermalSensorSmm_LIBS =\
+ $(EFIGUIDLIB)\
+ $(EDKFRAMEWORKGUIDLIB)\
+ $(EDKPROTOCOLLIB)\
+ $(EDKFRAMEWORKPROTOCOLLIB)\
+ $(EdkIIGlueBaseLib_LIB)\
+!IF "$(x64_BUILD)"=="1"
+ $(EdkIIGlueBaseLibX64_LIB)\
+!ELSE
+ $(EdkIIGlueBaseLibIA32_LIB)\
+!ENDIF
+ $(EdkIIGlueBaseMemoryLib_LIB)\
+ $(EdkIIGlueDxeReportStatusCodeLib_LIB)\
+ $(EdkIIGlueDxeDebugLibReportStatusCode_LIB)\
+ $(EdkIIGlueBaseIoLibIntrinsic_LIB)\
+ $(EdkIIGlueSmmRuntimeDxeReportStatusCodeLib_LIB)\
+ $(EdkIIGlueUefiBootServicesTableLib_LIB)\
+ $(EdkIIGlueDxeMemoryAllocationLib_LIB)\
+ $(EdkIIGlueBasePciLibPciExpress_LIB)\
+ $(CpuProtocolLib_LIB)\
+ $(EdkIIGlueBasePciExpressLib_LIB)\
+ $(PpmAslUpdateLib_LIB)\
+ $(SmmIoLib_LIB)\
+ $(SmmKscLib_LIB)\
+ $(DTSHookLib_LIB)\
+ $(PchPlatformSmmLib_LIB)
+
+DigitalThermalSensorSmmBin : $(DigitalThermalSensorSmm_LIBS)
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\DigitalThermalSensorSmm.mak all\
+ MAKEFILE=$(BUILD_DIR)\DigitalThermalSensorSmm.mak \
+ "MY_INCLUDES=$(DigitalThermalSensorSmm_MY_INCLUDES)" \
+ "MY_DEFINES=$(DigitalThermalSensorSmm_DEFINES)"\
+ OBJECTS="$(DigitalThermalSensorSmm_OBJECTS)" \
+ GUID=77A6009E-116E-464D-8EF8-B35201A022DD\
+ ENTRY_POINT=_ModuleEntryPoint \
+ TYPE=RT_DRIVER \
+ EDKIIModule=SMMDRIVER\
+ DEPEX1=$(DigitalThermalSensorSmm_DIR)\DigitalThermalSensorSmm.dxs \
+ DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX \
+ COMPRESS=1
+
diff --git a/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.sdl b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.sdl
new file mode 100644
index 0000000..a28ccce
--- /dev/null
+++ b/ReferenceCode/Haswell/DTS/Smm/DigitalThermalSensorSmm.sdl
@@ -0,0 +1,25 @@
+TOKEN
+ Name = "Haswell_DigitalThermalSensorSmm_SUPPORT"
+ Value = "1"
+ Help = "Main switch to include Haswell DigitalThermalSensorSmm driver to the Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+End
+
+PATH
+ Name = "DigitalThermalSensorSmm_DIR"
+End
+
+MODULE
+ Help = "Includes DigitalThermalSensorSmm.mak to Project"
+ File = "DigitalThermalSensorSmm.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\DigitalThermalSensorSmm.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End
diff --git a/ReferenceCode/Haswell/Docs/Haswell_CPU_RC_ReleaseNotes.pdf b/ReferenceCode/Haswell/Docs/Haswell_CPU_RC_ReleaseNotes.pdf
new file mode 100644
index 0000000..14be742
--- /dev/null
+++ b/ReferenceCode/Haswell/Docs/Haswell_CPU_RC_ReleaseNotes.pdf
Binary files differ
diff --git a/ReferenceCode/Haswell/Docs/Intel Haswell Processor Reference Code Specification_1.9.0.pdf b/ReferenceCode/Haswell/Docs/Intel Haswell Processor Reference Code Specification_1.9.0.pdf
new file mode 100644
index 0000000..0fe80ce
--- /dev/null
+++ b/ReferenceCode/Haswell/Docs/Intel Haswell Processor Reference Code Specification_1.9.0.pdf
Binary files differ
diff --git a/ReferenceCode/Haswell/Docs/RcCpuApi.chm b/ReferenceCode/Haswell/Docs/RcCpuApi.chm
new file mode 100644
index 0000000..8b4f925
--- /dev/null
+++ b/ReferenceCode/Haswell/Docs/RcCpuApi.chm
Binary files differ
diff --git a/ReferenceCode/Haswell/Docs/ReleaseNotes.txt b/ReferenceCode/Haswell/Docs/ReleaseNotes.txt
new file mode 100644
index 0000000..734f956
--- /dev/null
+++ b/ReferenceCode/Haswell/Docs/ReleaseNotes.txt
@@ -0,0 +1,54 @@
+;***********************************************************************;
+;* *;
+;* Intel(r) Restricted Secret *;
+;* *;
+;* Haswell CPU Reference Code *;
+;* *;
+;* PCCG Systems Software Engineering *;
+;* *;
+;* Copyright (c) 2014 Intel Corp. *;
+;* *;
+;* This program has been developed by Intel Corporation. *;
+;* Licensee has Intel's permission to incorporate this source code*;
+;* into their product, royalty free. This source code may NOT be *;
+;* redistributed to anyone without Intel's written permission. *;
+;* *;
+;* Intel specifically disclaims all warranties, express or *;
+;* implied, and all liability, including consequential and other *;
+;* indirect damages, for the use of this code, including liability*;
+;* for infringement of any proprietary rights, and including the *;
+;* warranties of merchantability and fitness for a particular *;
+;* purpose. Intel does not assume any responsibility for any *;
+;* errors which may appear in this code nor any responsibility to *;
+;* update it. *;
+;* *;
+;***********************************************************************;
+
+
+Purpose of Reference Code
+
+------------------------------------------------------------------------------
+
+This is Reference code for initialization of the Haswell Processor.
+This supports detection and initialization of various functionalities in
+CPU. The algorithm used in this file follows the algorithm provided in the
+Haswell Processor Family BIOS Writer's Guide.
+
+------------------------------------------------------------------------------
+
+
+Framework Haswell CPU Reference Code Version Information
+Revision: 1.9.0
+Release Date: Nov 6, 2014
+
+
+Release Details
+---------------
+
+EDK version: Edk-Dev-Snapshot-20061117 + EDK1117PatchV8
+Compiler tools version: VS2008 + SP1
+CRB BAT version: HLPT138
+
+References
+----------
+Haswell Processor Family BIOS Writer's Guide 1.8.0 \ No newline at end of file
diff --git a/ReferenceCode/Haswell/Guid/CpuGuidLib.cif b/ReferenceCode/Haswell/Guid/CpuGuidLib.cif
new file mode 100644
index 0000000..8baf1c5
--- /dev/null
+++ b/ReferenceCode/Haswell/Guid/CpuGuidLib.cif
@@ -0,0 +1,24 @@
+<component>
+ name = "CpuGuidLib"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\Guid\"
+ RefName = "CpuGuidLib"
+[files]
+"CpuGuidLib.sdl"
+"CpuGuidLib.mak"
+"CpuGuidLib.inf"
+"HtBistHob\HtBistHob.c"
+"HtBistHob\HtBistHob.h"
+"PowerMgmtAcpiTableStorage\PowerMgmtAcpiTableStorage.c"
+"PowerMgmtAcpiTableStorage\PowerMgmtAcpiTableStorage.h"
+"PoweronHob\PoweronHob.c"
+"PoweronHob\PoweronHob.h"
+"SmramCpuDataHeader\SmramCpuDataHeader.c"
+"SmramCpuDataHeader\SmramCpuDataHeader.h"
+"SmramCpuDataVariable\SmramCpuDataVariable.c"
+"SmramCpuDataVariable\SmramCpuDataVariable.h"
+"TxtInfoHob\TxtInfoHob.c"
+"TxtInfoHob\TxtInfoHob.h"
+"TxtOneTouch\TxtOneTouch.c"
+"TxtOneTouch\TxtOneTouch.h"
+<endComponent>
diff --git a/ReferenceCode/Haswell/Guid/CpuGuidLib.inf b/ReferenceCode/Haswell/Guid/CpuGuidLib.inf
new file mode 100644
index 0000000..12a43c2
--- /dev/null
+++ b/ReferenceCode/Haswell/Guid/CpuGuidLib.inf
@@ -0,0 +1,68 @@
+## @file
+# Component description file for CpuGuidLib
+#
+#@copyright
+# Copyright (c) 2008 - 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
+#
+
+[defines]
+BASE_NAME = CpuGuidLib
+COMPONENT_TYPE = LIBRARY
+
+[sources.common]
+ HtBistHob/HtBistHob.c
+ HtBistHob/HtBistHob.h
+ SmramCpuDataVariable/SmramCpuDataVariable.c
+ SmramCpuDataVariable/SmramCpuDataVariable.h
+ SmramCpuDataHeader/SmramCpuDataHeader.c
+ SmramCpuDataHeader/SmramCpuDataHeader.h
+ PoweronHob/PoweronHob.c
+ PoweronHob/PoweronHob.h
+ PowerMgmtAcpiTableStorage/PowerMgmtAcpiTableStorage.h
+ PowerMgmtAcpiTableStorage/PowerMgmtAcpiTableStorage.c
+ TxtInfoHob/TxtInfoHob.c
+ TxtInfoHob/TxtInfoHob.h
+ TxtOneTouch/TxtOneTouch.c
+ TxtOneTouch/TxtOneTouch.h
+
+[includes.common]
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Pei/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)
+
+#
+# Edk II Glue Library, some hearder are included by R9 header so have to include
+#
+
+ $(EFI_SOURCE)
+ $(EFI_SOURCE)/Framework
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+
+[nmake.common]
+C_STD_INCLUDE=
diff --git a/ReferenceCode/Haswell/Guid/CpuGuidLib.mak b/ReferenceCode/Haswell/Guid/CpuGuidLib.mak
new file mode 100644
index 0000000..b569f92
--- /dev/null
+++ b/ReferenceCode/Haswell/Guid/CpuGuidLib.mak
@@ -0,0 +1,19 @@
+# MAK file for the ModulePart:PpmGuidLib
+
+$(CpuGuidLib_LIB) : CpuGuidLib
+
+CpuGuidLib : $(BUILD_DIR)\CpuGuidLib.mak CpuGuidLibBin
+
+$(BUILD_DIR)\CpuGuidLib.mak : $(CpuGuidLib_DIR)\$(@B).cif $(CpuGuidLib_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(CpuGuidLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+CpuGuidLibBin :
+ $(MAKE) /$(MAKEFLAGS) $(EDK_DEFAULTS)\
+ /f $(BUILD_DIR)\CpuGuidLib.mak all\
+ "MY_INCLUDES=$(EDK_INCLUDES) $(EdkIIGlueLib_INCLUDES) $(PROJECT_CPU_INCLUDES)" \
+ TYPE=LIBRARY \
+ LIBRARY_NAME=$(CpuGuidLib_LIB)
+ $(MAKE) /$(MAKEFLAGS) $(EDK_DEFAULTS) BUILD_DIR=$(BUILD_DIR)\IA32\
+ /f $(BUILD_DIR)\CpuGuidLib.mak all\
+ "MY_INCLUDES=$(EDK_INCLUDES) $(EdkIIGlueLib_INCLUDES) $(PROJECT_CPU_INCLUDES)" \
+ TYPE=PEI_LIBRARY
diff --git a/ReferenceCode/Haswell/Guid/CpuGuidLib.sdl b/ReferenceCode/Haswell/Guid/CpuGuidLib.sdl
new file mode 100644
index 0000000..f328927
--- /dev/null
+++ b/ReferenceCode/Haswell/Guid/CpuGuidLib.sdl
@@ -0,0 +1,26 @@
+TOKEN
+ Name = CpuGuidLib_SUPPORT
+ Value = "1"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+ Help = "Main switch to enable CpuGuidLib support in Project"
+End
+
+MODULE
+ Help = "Includes CpuGuidLib.mak to Project"
+ File = "CpuGuidLib.mak"
+End
+
+PATH
+ Name = "CpuGuidLib_DIR"
+End
+
+TOKEN
+ Name = "CpuGuidLib_LIB"
+ Value = "$$(LIB_BUILD_DIR)\CpuGuidLib.lib"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
diff --git a/ReferenceCode/Haswell/Guid/HtBistHob/HtBistHob.c b/ReferenceCode/Haswell/Guid/HtBistHob/HtBistHob.c
new file mode 100644
index 0000000..a2457c7
--- /dev/null
+++ b/ReferenceCode/Haswell/Guid/HtBistHob/HtBistHob.c
@@ -0,0 +1,24 @@
+/** @file
+ GUIDs used for HT BIST Status HOB entries in the HOB list.
+
+@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 'Framework Code' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may not be modified, except as allowed by
+ additional terms of your license agreement.
+**/
+#include "Tiano.h"
+#include EFI_GUID_DEFINITION (HtBistHob)
+
+EFI_GUID gEfiHtBistHobGuid = EFI_HT_BIST_HOB_GUID;
+
+EFI_GUID_STRING(&gEfiHtBistHobGuid, "HT BIST HOB", "HT BIST HOB GUID for HOB list.");
diff --git a/ReferenceCode/Haswell/Guid/HtBistHob/HtBistHob.h b/ReferenceCode/Haswell/Guid/HtBistHob/HtBistHob.h
new file mode 100644
index 0000000..bd5e593
--- /dev/null
+++ b/ReferenceCode/Haswell/Guid/HtBistHob/HtBistHob.h
@@ -0,0 +1,29 @@
+/** @file
+ GUID used for HT BIST Status HOB entries in the HOB list.
+
+@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 'Framework Code' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may not be modified, except as allowed by
+ additional terms of your license agreement.
+**/
+#ifndef _HT_BIST_HOB_GUID_H_
+#define _HT_BIST_HOB_GUID_H_
+
+#define EFI_HT_BIST_HOB_GUID \
+ { \
+ 0xbe644001, 0xe7d4, 0x48b1, 0xb0, 0x96, 0x8b, 0xa0, 0x47, 0xbc, 0x7a, 0xe7 \
+ }
+
+extern EFI_GUID gEfiHtBistHobGuid;
+
+#endif
diff --git a/ReferenceCode/Haswell/Guid/PowerMgmtAcpiTableStorage/PowerMgmtAcpiTableStorage.c b/ReferenceCode/Haswell/Guid/PowerMgmtAcpiTableStorage/PowerMgmtAcpiTableStorage.c
new file mode 100644
index 0000000..f8878dd
--- /dev/null
+++ b/ReferenceCode/Haswell/Guid/PowerMgmtAcpiTableStorage/PowerMgmtAcpiTableStorage.c
@@ -0,0 +1,40 @@
+/** @file
+ The GUID definition for power management ACPI table storage file name
+
+@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 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
+**/
+
+///
+/// Statements that include other files
+///
+#include "EdkIIGlueDxe.h"
+#include "PowerMgmtAcpiTableStorage.h"
+
+///
+/// Protocol GUID definition
+///
+EFI_GUID gPowerMgmtAcpiTableStorageGuid = POWER_MGMT_ACPI_TABLE_STORAGE_GUID;
+
+///
+/// Protocol description
+///
+EFI_GUID_STRING
+(
+ &gPowerMgmtAcpiTableStorageGuid, "Power Management ACPI Table Storage File Name",
+ "Power Management ACPI Table Storage file name GUID"
+);
diff --git a/ReferenceCode/Haswell/Guid/PowerMgmtAcpiTableStorage/PowerMgmtAcpiTableStorage.h b/ReferenceCode/Haswell/Guid/PowerMgmtAcpiTableStorage/PowerMgmtAcpiTableStorage.h
new file mode 100644
index 0000000..fa96723
--- /dev/null
+++ b/ReferenceCode/Haswell/Guid/PowerMgmtAcpiTableStorage/PowerMgmtAcpiTableStorage.h
@@ -0,0 +1,35 @@
+/** @file
+ GUID definition for the Power Management ACPI table storage file name
+
+@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 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
+**/
+#ifndef _POWER_MGMT_ACPI_TABLE_STORAGE_H_
+#define _POWER_MGMT_ACPI_TABLE_STORAGE_H_
+
+///
+/// Power Mgmt policy provided by platform for ACPI Table Storage
+/// {299141BB-211A-48a5-92C0-6F9A0A3A006E}
+///
+#define POWER_MGMT_ACPI_TABLE_STORAGE_GUID \
+ { \
+ 0x299141bb, 0x211a, 0x48a5, 0x92, 0xc0, 0x6f, 0x9a, 0xa, 0x3a, 0x0, 0x6e \
+ }
+
+extern EFI_GUID gPowerMgmtAcpiTableStorageGuid;
+
+#endif
diff --git a/ReferenceCode/Haswell/Guid/PoweronHob/PoweronHob.c b/ReferenceCode/Haswell/Guid/PoweronHob/PoweronHob.c
new file mode 100644
index 0000000..660d5d1
--- /dev/null
+++ b/ReferenceCode/Haswell/Guid/PoweronHob/PoweronHob.c
@@ -0,0 +1,24 @@
+/** @file
+ GUIDs used for PowerOn boot mode (not reset).
+
+@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 'Framework Code' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may not be modified, except as allowed by
+ additional terms of your license agreement.
+**/
+#include "Tiano.h"
+#include EFI_GUID_DEFINITION (PowerOnHob)
+
+EFI_GUID gEfiPowerOnHobGuid = EFI_POWER_ON_HOB_GUID;
+
+EFI_GUID_STRING(&gEfiPowerOnHobGuid, "Power On HOB", "Hob GUID for Power On boot mode");
diff --git a/ReferenceCode/Haswell/Guid/PoweronHob/PoweronHob.h b/ReferenceCode/Haswell/Guid/PoweronHob/PoweronHob.h
new file mode 100644
index 0000000..9d0487b
--- /dev/null
+++ b/ReferenceCode/Haswell/Guid/PoweronHob/PoweronHob.h
@@ -0,0 +1,29 @@
+/** @file
+ GUID for Power On boot mode.
+
+@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 'Framework Code' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may not be modified, except as allowed by
+ additional terms of your license agreement.
+**/
+#ifndef _POWER_ON_HOB_GUID_H_
+#define _POWER_ON_HOB_GUID_H_
+
+#define EFI_POWER_ON_HOB_GUID \
+ { \
+ 0x468a601, 0xc535, 0x46fd, 0xa9, 0x5d, 0xbb, 0xab, 0x99, 0x1b, 0x17, 0x8c \
+ }
+
+extern EFI_GUID gEfiPowerOnHobGuid;
+
+#endif
diff --git a/ReferenceCode/Haswell/Guid/SmramCpuDataHeader/SmramCpuDataHeader.c b/ReferenceCode/Haswell/Guid/SmramCpuDataHeader/SmramCpuDataHeader.c
new file mode 100644
index 0000000..76f25fe
--- /dev/null
+++ b/ReferenceCode/Haswell/Guid/SmramCpuDataHeader/SmramCpuDataHeader.c
@@ -0,0 +1,24 @@
+/** @file
+ GUIDs used for SMRAM CPU DATA Header as signature for search
+
+@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 'Framework Code' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may not be modified, except as allowed by
+ additional terms of your license agreement.
+**/
+#include "Tiano.h"
+#include EFI_GUID_DEFINITION (SmramCpuDataHeader)
+
+EFI_GUID gSmramCpuDataHeaderGuid = SMRAM_CPU_DATA_HEADER_GUID;
+
+EFI_GUID_STRING(&gSmramCpuDataHeaderGuid, "SMRAM CPU DATA Header", "SMRAM CPU DATA Header GUID");
diff --git a/ReferenceCode/Haswell/Guid/SmramCpuDataHeader/SmramCpuDataHeader.h b/ReferenceCode/Haswell/Guid/SmramCpuDataHeader/SmramCpuDataHeader.h
new file mode 100644
index 0000000..fd8c4ea
--- /dev/null
+++ b/ReferenceCode/Haswell/Guid/SmramCpuDataHeader/SmramCpuDataHeader.h
@@ -0,0 +1,32 @@
+/** @file
+ GUIDs used for SMRAM CPU DATA Header signature
+
+@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 'Framework Code' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may not be modified, except as allowed by
+ additional terms of your license agreement.
+**/
+#ifndef _SMRAM_CPU_DATA_HEADER_H_
+#define _SMRAM_CPU_DATA_HEADER_H_
+
+///
+/// SMRAM CPU DATA Header for search by CpuS3Peim
+///
+#define SMRAM_CPU_DATA_HEADER_GUID \
+ { \
+ 0x5848fd2d, 0xd6af, 0x474b, 0x82, 0x75, 0x95, 0xdd, 0xe7, 0x0a, 0xe8, 0x23 \
+ }
+
+extern EFI_GUID gSmramCpuDataHeaderGuid;
+
+#endif
diff --git a/ReferenceCode/Haswell/Guid/SmramCpuDataVariable/SmramCpuDataVariable.c b/ReferenceCode/Haswell/Guid/SmramCpuDataVariable/SmramCpuDataVariable.c
new file mode 100644
index 0000000..9448ca9
--- /dev/null
+++ b/ReferenceCode/Haswell/Guid/SmramCpuDataVariable/SmramCpuDataVariable.c
@@ -0,0 +1,24 @@
+/** @file
+ GUIDs used for ACPI CPU DATA Variable.
+
+@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 'Framework Code' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may not be modified, except as allowed by
+ additional terms of your license agreement.
+**/
+#include "Tiano.h"
+#include EFI_GUID_DEFINITION (SmramCpuDataVariable)
+
+EFI_GUID gSmramCpuDataVariableGuid = SMRAM_CPU_DATA_VARIABLE_GUID;
+
+EFI_GUID_STRING(&gSmramCpuDataVariableGuid, "SMRAM CPU DATA Variable", "SMRAM CPU DATA Variable GUID");
diff --git a/ReferenceCode/Haswell/Guid/SmramCpuDataVariable/SmramCpuDataVariable.h b/ReferenceCode/Haswell/Guid/SmramCpuDataVariable/SmramCpuDataVariable.h
new file mode 100644
index 0000000..33a66b9
--- /dev/null
+++ b/ReferenceCode/Haswell/Guid/SmramCpuDataVariable/SmramCpuDataVariable.h
@@ -0,0 +1,46 @@
+/** @file
+ GUIDs used for SMRAM CPU DATA Variable to keep 2 locations for copying data from
+ regular memory to SMM memory
+
+@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 'Framework Code' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may not be modified, except as allowed by
+ additional terms of your license agreement.
+**/
+#ifndef _SMRAM_CPU_DATA_VARIABLE_H_
+#define _SMRAM_CPU_DATA_VARIABLE_H_
+
+///
+/// CPU Driver will maintain ACPI CPU DATA in regular memory,
+/// 1. CpuInitDxe driver will allocate SMM memory, and normal memory
+/// 2. Save both location in SMRAM_CPU_DATA_VARIABLE
+/// 3. Issue SMM_FROM_CPU_DRIVER_SAVE_INFO SW SMI to ask SMM driver to
+/// copy data to SMRAM with signature.
+/// 4. In S3 path, CPUS3 retrieves data by search signature in SMRAM.
+///
+#define SMRAM_CPU_DATA_VARIABLE_GUID \
+ { \
+ 0x429501d9, 0xe447, 0x40f4, 0x86, 0x7b, 0x75, 0xc9, 0x3a, 0x1d, 0xb5, 0x4e \
+ }
+
+#define SMRAM_CPU_DATA_VARIABLE L"SmramCpuDataVar"
+
+typedef struct {
+ EFI_PHYSICAL_ADDRESS LockBoxData;
+ EFI_PHYSICAL_ADDRESS SmramCpuData;
+ UINT64 LockBoxSize;
+} SMRAM_CPU_DATA_ADDRESS;
+
+extern EFI_GUID gSmramCpuDataVariableGuid;
+
+#endif
diff --git a/ReferenceCode/Haswell/Guid/TxtInfoHob/TxtInfoHob.c b/ReferenceCode/Haswell/Guid/TxtInfoHob/TxtInfoHob.c
new file mode 100644
index 0000000..6803c27
--- /dev/null
+++ b/ReferenceCode/Haswell/Guid/TxtInfoHob/TxtInfoHob.c
@@ -0,0 +1,33 @@
+/** @file
+ This file contains GUID to use for creation of TXT Info Hob.
+
+@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 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
+**/
+
+///
+/// External include files do NOT need to be explicitly specified in real EDKII
+/// environment
+///
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include EFI_GUID_DEFINITION (TxtInfoHob)
+#endif
+
+EFI_GUID gTxtInfoHobGuid = TXT_INFO_HOB_GUID;
+
+EFI_GUID_STRING(&gTxtInfoHobGuid, "TXT Info Hob", "TXT Info Hob");
diff --git a/ReferenceCode/Haswell/Guid/TxtInfoHob/TxtInfoHob.h b/ReferenceCode/Haswell/Guid/TxtInfoHob/TxtInfoHob.h
new file mode 100644
index 0000000..e006497
--- /dev/null
+++ b/ReferenceCode/Haswell/Guid/TxtInfoHob/TxtInfoHob.h
@@ -0,0 +1,65 @@
+/** @file
+ This file contains definitions required for creation of TXT Info HOB.
+
+@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 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
+**/
+#ifndef _TXT_HOB_H_
+#define _TXT_HOB_H_
+
+#define TXT_INFO_HOB_GUID \
+ { \
+ 0x2986883F, 0x88E0, 0x48d0, 0x4B, 0x82, 0x20, 0xC2, 0x69, 0x48, 0xDD, 0xAC \
+ }
+
+extern EFI_GUID gTxtInfoHobGuid;
+
+#pragma pack(push, 1)
+
+typedef struct {
+ BOOLEAN ChipsetIsTxtCapable;
+ UINT8 TxtMode;
+ UINT64 PmBase;
+ UINT64 SinitMemorySize;
+ UINT64 TxtHeapMemorySize;
+ EFI_PHYSICAL_ADDRESS TxtDprMemoryBase;
+ UINT64 TxtDprMemorySize;
+ EFI_PHYSICAL_ADDRESS BiosAcmBase;
+ UINT64 BiosAcmSize;
+ EFI_PHYSICAL_ADDRESS McuUpdateDataAddr;
+ EFI_PHYSICAL_ADDRESS SinitAcmBase;
+ UINT64 SinitAcmSize;
+ UINT64 TgaSize;
+ EFI_PHYSICAL_ADDRESS TxtLcpPdBase;
+ UINT64 TxtLcpPdSize;
+ UINT64 Flags;
+} TXT_INFO_DATA;
+
+#define FLAGS0 0x1
+#define TXT_CPU_RESET_REQUIRED 0x2
+#define TPM_INIT_FAILED 0x4
+
+#define CMOS_INDEX_PORT 0x70
+#define CMOS_DATA_PORT 0x71
+
+typedef struct {
+ EFI_HOB_GUID_TYPE EfiHobGuidType;
+ TXT_INFO_DATA Data;
+} TXT_INFO_HOB;
+#pragma pack(pop)
+
+#endif
diff --git a/ReferenceCode/Haswell/Guid/TxtOneTouch/TxtOneTouch.c b/ReferenceCode/Haswell/Guid/TxtOneTouch/TxtOneTouch.c
new file mode 100644
index 0000000..acdeafc
--- /dev/null
+++ b/ReferenceCode/Haswell/Guid/TxtOneTouch/TxtOneTouch.c
@@ -0,0 +1,33 @@
+/** @file
+ This file contains definitions required for One-Touch function.
+
+@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 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
+**/
+
+///
+/// External include files do NOT need to be explicitly specified in real EDKII
+/// environment
+///
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include EFI_GUID_DEFINITION (TxtOneTouch)
+#endif
+
+EFI_GUID gTxtOneTouchGuid = TXT_ONE_TOUCH_GUID;
+
+EFI_GUID_STRING(&gTxtOneTouchGuid, "TXT One_Touch GUID", "TXT One_Touch GUID");
diff --git a/ReferenceCode/Haswell/Guid/TxtOneTouch/TxtOneTouch.h b/ReferenceCode/Haswell/Guid/TxtOneTouch/TxtOneTouch.h
new file mode 100644
index 0000000..a99b42e
--- /dev/null
+++ b/ReferenceCode/Haswell/Guid/TxtOneTouch/TxtOneTouch.h
@@ -0,0 +1,53 @@
+/** @file
+ This file contains definitions required for One-Touch function.
+
+@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 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
+**/
+#ifndef _TXT_ONE_TOUCH_H_
+#define _TXT_ONE_TOUCH_H_
+
+#define TXT_ONE_TOUCH_GUID \
+ { \
+ 0x3D989471, 0xCFAC, 0x46B7, 0x9B, 0x1C, 0x8, 0x43, 0x1, 0x9, 0x40, 0x2D \
+ }
+
+extern EFI_GUID gTxtOneTouchGuid;
+
+//
+// Operation
+//
+#define ENABLE_VT 128
+#define DISABLE_VT_TXT 129
+#define ENABLE_VTD 130
+#define DISABLE_VTD_TXT 131
+#define ENABLE_ACTTPM_VT_VTD_TXT_DISABLE_STM 132
+#define ENABLE_ACTTPM_VT_VTD_TXT_STM 133
+#define DISABLE_STM 134
+#define DISABLE_TXT_STM 135
+#define DISABLE_SENTER_VMX 136 ///< optional
+#define ENABLE_VMX_SMX_ONLY 137 ///< optional
+#define ENABLE_VMX_OUTSIDE_SMX 138 ///< optional
+#define ENABLE_VMX 139 ///< optional
+#define ENABLE_SENTER_ONLY 140 ///< optional
+#define ENABLE_SENTER_VMX_IN_SMX 141 ///< optional
+#define ENABLE_SENTER_VMX_OUTSIDE_SMX 142 ///< optional
+#define ENABLE_SENTER_VMX 143 ///< optional
+#define SET_NO_TXT_MAINTENANCE_FALSE 159
+#define SET_NO_TXT_MAINTENANCE_TRUE 160
+
+#endif
diff --git a/ReferenceCode/Haswell/Haswell.chm b/ReferenceCode/Haswell/Haswell.chm
new file mode 100644
index 0000000..ddbe518
--- /dev/null
+++ b/ReferenceCode/Haswell/Haswell.chm
Binary files differ
diff --git a/ReferenceCode/Haswell/HaswellPkg.cif b/ReferenceCode/Haswell/HaswellPkg.cif
new file mode 100644
index 0000000..a6cfa11
--- /dev/null
+++ b/ReferenceCode/Haswell/HaswellPkg.cif
@@ -0,0 +1,12 @@
+<component>
+ name = "Intel Haswell"
+ category = CPU
+ LocalRoot = "ReferenceCode\Haswell\"
+ RefName = "Intel Haswell"
+[files]
+"HaswellPkg.sdl"
+"Haswell.chm"
+[parts]
+"Haswell Cpu RC PKG"
+"AMI Cpu PKG"
+<endComponent>
diff --git a/ReferenceCode/Haswell/HaswellPkg.sdl b/ReferenceCode/Haswell/HaswellPkg.sdl
new file mode 100644
index 0000000..e3e0b67
--- /dev/null
+++ b/ReferenceCode/Haswell/HaswellPkg.sdl
@@ -0,0 +1,10 @@
+TOKEN
+ Name = "HaswellPkg_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable Ivy Bridge support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+End
diff --git a/ReferenceCode/Haswell/HaswellRcPkg.cif b/ReferenceCode/Haswell/HaswellRcPkg.cif
new file mode 100644
index 0000000..fc84bee
--- /dev/null
+++ b/ReferenceCode/Haswell/HaswellRcPkg.cif
@@ -0,0 +1,46 @@
+<component>
+ name = "Intel Haswell Cpu RC PKG"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\"
+ RefName = "Haswell Cpu RC PKG"
+[files]
+"HaswellRcPkg.sdl"
+"Docs\RcCpuApi.chm"
+"Docs\Haswell_CPU_RC_ReleaseNotes.pdf"
+"Docs\ReleaseNotes.txt"
+"Docs\Intel Haswell Processor Reference Code Specification_1.9.0.pdf"
+[parts]
+"CpuInitDxe"
+"CpuInitPei"
+"CpuGuidLib"
+"CpuProtocolLib"
+"CpuRcInclude"
+"CpuPpiLib"
+"CpuRcSec"
+"ThunkLib"
+"CpuS3Peim"
+"PowerManagementAcpiTables"
+"PowerMgmtInit"
+"PowerMgmtS3"
+"Cpu Policy Pei"
+"Cpu Policy Dxe"
+"PpmAslUpdateLib"
+"CpuSampleCode"
+"CpuPlatformLib"
+"OcPlatformLib"
+"DigitalThermalSensorSmm"
+"SmmKscLib"
+"SmmIoLib"
+"DTSHookLib"
+"TxtPei"
+"TxtDxe"
+"TxtBiosAcm"
+"TxtTools"
+"TxtOneTouchDxe"
+"CpuSampleCodeProtocolLib"
+"OcPlatformLib"
+"TxtLib"
+"BootGuardRevocationLib"
+"BootGuardLib"
+"BootGuardTpmEventLogLib"
+<endComponent>
diff --git a/ReferenceCode/Haswell/HaswellRcPkg.sdl b/ReferenceCode/Haswell/HaswellRcPkg.sdl
new file mode 100644
index 0000000..30fba98
--- /dev/null
+++ b/ReferenceCode/Haswell/HaswellRcPkg.sdl
@@ -0,0 +1,206 @@
+TOKEN
+ Name = "INTEL_CPURC_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable Ivy Bridge CPU reference code support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+End
+
+TOKEN
+ Name = "BIST_SUPPORT"
+ Value = "0"
+ Help = "Due to Intel sighting report, do not turn on this token."
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "CpuRatioOverride_Support"
+ Value = "0"
+ Help = "Due to Intel sighting report, do not turn on this token."
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "DcaState_token"
+ Value = "0"
+ Help = "Due to Intel sighting report, do not turn on this token."
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "FastString_token"
+ Value = "1"
+ Help = "Token for setup CPU Policy protocol."
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "MachineCheckEnable_token"
+ Value = "1"
+ Help = "Token for setup CPU Policy protocol."
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+#TOKEN
+# Name = "MonitorMwaitEnable_token"
+# Value = "1"
+# Help = "Token for setup CPU Policy protocol."
+# TokenType = Boolean
+# TargetMAK = Yes
+# TargetH = Yes
+#End
+
+#-TOKEN
+#- Name = "XapicEnable_token"
+#- Value = "0"
+#- Help = "Token for setup CPU Policy protocol."
+#- TokenType = Boolean
+#- TargetMAK = Yes
+#- TargetH = Yes
+#-End
+
+#TOKEN
+# Name = "BspSelectione_token"
+# Value = "0"
+# Help = "Token for setup CPU Policy protocol."
+# TokenType = Boolean
+# TargetMAK = Yes
+# TargetH = Yes
+#End
+
+TOKEN
+ Name = "DcaPrefetchDelayValue_token"
+ Value = "4"
+ Help = "Token for setup CPU Policy protocol."
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "VirtualWireMode_token"
+ Value = "0"
+ Help = "Token for setup CPU Policy protocol."
+ TokenType = Boolean
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+PATH
+#- Name = "IvyBridgePkg_DIR"
+ Name = "PROJECT_CPU_ROOT"
+End
+
+PATH
+ Name = "PROJECT_PCH_ROOT"
+ Path = "ReferenceCode\Chipset\LynxPoint"
+End
+
+#-PATH
+#- Name = "IvyBridgePkgPei_DIR"
+#-End
+
+#-PATH
+#- Name = "IvyBridgePkgDxe_DIR"
+#-End
+
+ELINK
+#- Name = "IvyBridgePkg_INCLUDES"
+ Name = "PROJECT_CPU_INCLUDES"
+ InvokeOrder = ReplaceParent
+End
+
+#-ELINK
+#- Name = "IvyBridgePkgPei_INCLUDES"
+#- InvokeOrder = ReplaceParent
+#-End
+#-
+#-ELINK
+#- Name = "IvyBridgePkgDxe_INCLUDES"
+#- InvokeOrder = ReplaceParent
+#-End
+
+ELINK
+ Name = "/I$(PROJECT_CPU_ROOT)"
+ Parent = "PROJECT_CPU_INCLUDES"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "/I$(PROJECT_CPU_ROOT)\Include"
+ Parent = "PROJECT_CPU_INCLUDES"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "/I$(PROJECT_CPU_ROOT)\Include\Library"
+ Parent = "PROJECT_CPU_INCLUDES"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "/I$(PROJECT_CPU_ROOT)\CpuInit\Dxe\x64"
+ Parent = "PROJECT_CPU_INCLUDES"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "/I$(PROJECT_CPU_ROOT)\SampleCode\Include"
+ Parent = "PROJECT_CPU_INCLUDES"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "/I$(PROJECT_CPU_ROOT)\SampleCode"
+ Parent = "PROJECT_CPU_INCLUDES"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "/I$(PROJECT_PCH_ROOT)\Include"
+ Parent = "PROJECT_CPU_INCLUDES"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "/I$(PROJECT_PCH_ROOT)\Include\Library"
+ Parent = "PROJECT_CPU_INCLUDES"
+ InvokeOrder = AfterParent
+End
+
+#-ELINK
+#- Name = "/I$(IvyBridgePkg_DIR)\SampleCode\CpuPolicyInit\Pei"
+#- Parent = "IvyBridgePkgPei_INCLUDES"
+#- InvokeOrder = AfterParent
+#-End
+#-
+#-ELINK
+#- Name = "/I$(IvyBridgePkg_DIR)\CpuInit\Dxe"
+#- Parent = "IvyBridgePkgDxe_INCLUDES"
+#- InvokeOrder = AfterParent
+#-End
+#-
+#-ELINK
+#- Name = "/I$(IvyBridgePkg_DIR)\SampleCode\CpuPolicyInit\Dxe"
+#- Parent = "IvyBridgePkgDxe_INCLUDES"
+#- InvokeOrder = AfterParent
+#-End
+#-
+#-ELINK
+#- Name = "/I$(IvyBridgePkg_DIR)\SampleCode\CpuPolicyInit\Dxe\x64"
+#- Parent = "IvyBridgePkgDxe_INCLUDES"
+#- InvokeOrder = AfterParent
+#-End
diff --git a/ReferenceCode/Haswell/Include/CommonIncludes.h b/ReferenceCode/Haswell/Include/CommonIncludes.h
new file mode 100644
index 0000000..4fe8b54
--- /dev/null
+++ b/ReferenceCode/Haswell/Include/CommonIncludes.h
@@ -0,0 +1,120 @@
+/** @file
+ This file defines common equates.
+
+@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 an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Mobile Silicon Support Module" and is
+ licensed for Intel Mobile 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
+**/
+#ifndef _COMMON_INCLUDES_H_
+#define _COMMON_INCLUDES_H_
+
+#define V_INTEL_VID 0x8086
+
+#ifndef STALL_ONE_MICRO_SECOND
+#define STALL_ONE_MICRO_SECOND 1
+#endif
+#ifndef STALL_ONE_MILLI_SECOND
+#define STALL_ONE_MILLI_SECOND 1000
+#endif
+//
+// Min Max
+//
+#define V_MIN(a, b) (((a) < (b)) ? (a) : (b))
+#define V_MAX(a, b) (((a) > (b)) ? (a) : (b))
+
+///
+/// Bit map macro
+///
+#ifndef BIT0
+
+#define BIT63 0x8000000000000000ULL
+#define BIT62 0x4000000000000000ULL
+#define BIT61 0x2000000000000000ULL
+#define BIT60 0x1000000000000000ULL
+#define BIT59 0x0800000000000000ULL
+#define BIT58 0x0400000000000000ULL
+#define BIT57 0x0200000000000000ULL
+#define BIT56 0x0100000000000000ULL
+#define BIT55 0x0080000000000000ULL
+#define BIT54 0x0040000000000000ULL
+#define BIT53 0x0020000000000000ULL
+#define BIT52 0x0010000000000000ULL
+#define BIT51 0x0008000000000000ULL
+#define BIT50 0x0004000000000000ULL
+#define BIT49 0x0002000000000000ULL
+#define BIT48 0x0001000000000000ULL
+#define BIT47 0x0000800000000000ULL
+#define BIT46 0x0000400000000000ULL
+#define BIT45 0x0000200000000000ULL
+#define BIT44 0x0000100000000000ULL
+#define BIT43 0x0000080000000000ULL
+#define BIT42 0x0000040000000000ULL
+#define BIT41 0x0000020000000000ULL
+#define BIT40 0x0000010000000000ULL
+#define BIT39 0x0000008000000000ULL
+#define BIT38 0x0000004000000000ULL
+#define BIT37 0x0000002000000000ULL
+#define BIT36 0x0000001000000000ULL
+#define BIT35 0x0000000800000000ULL
+#define BIT34 0x0000000400000000ULL
+#define BIT33 0x0000000200000000ULL
+#define BIT32 0x0000000100000000ULL
+
+#define BIT31 0x80000000
+#define BIT30 0x40000000
+#define BIT29 0x20000000
+#define BIT28 0x10000000
+#define BIT27 0x08000000
+#define BIT26 0x04000000
+#define BIT25 0x02000000
+#define BIT24 0x01000000
+#define BIT23 0x00800000
+#define BIT22 0x00400000
+#define BIT21 0x00200000
+#define BIT20 0x00100000
+#define BIT19 0x00080000
+#define BIT18 0x00040000
+#define BIT17 0x00020000
+#define BIT16 0x00010000
+#define BIT15 0x00008000
+#define BIT14 0x00004000
+#define BIT13 0x00002000
+#define BIT12 0x00001000
+#define BIT11 0x00000800
+#define BIT10 0x00000400
+#define BIT9 0x00000200
+#define BIT8 0x00000100
+#define BIT7 0x00000080
+#define BIT6 0x00000040
+#define BIT5 0x00000020
+#define BIT4 0x00000010
+#define BIT3 0x00000008
+#define BIT2 0x00000004
+#define BIT1 0x00000002
+#define BIT0 0x00000001
+#endif
+
+#define BITS(x) (1 << (x))
+
+/*
+Notes :
+ 1. Bit position always starts at 0.
+ 2. Following macros are applicable only for Word alligned integers.
+*/
+#define BIT(Pos, Value) (1 << (Pos) & (Value))
+#define BITRANGE(From, Width, Value) (((Value) >> (From)) & ((1 << (Width)) - 1))
+
+#endif
diff --git a/ReferenceCode/Haswell/Include/CpuAccess.h b/ReferenceCode/Haswell/Include/CpuAccess.h
new file mode 100644
index 0000000..e3dd024
--- /dev/null
+++ b/ReferenceCode/Haswell/Include/CpuAccess.h
@@ -0,0 +1,28 @@
+/** @file
+ Macros to simplify and abstract the interface to CPU configuration.
+
+@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 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
+**/
+#ifndef _CPUACCESS_H_
+#define _CPUACCESS_H_
+
+#include "CpuRegs.h"
+#include "CpuDataStruct.h"
+#include "CpuBaseLib.h"
+
+#endif
diff --git a/ReferenceCode/Haswell/Include/CpuBaseLib.h b/ReferenceCode/Haswell/Include/CpuBaseLib.h
new file mode 100644
index 0000000..87c8363
--- /dev/null
+++ b/ReferenceCode/Haswell/Include/CpuBaseLib.h
@@ -0,0 +1,193 @@
+/** @file
+
+@copyright
+ Copyright (c) 2004 - 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 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
+**/
+#ifndef _CPU_BASE_LIB_H
+#define _CPU_BASE_LIB_H
+
+///
+/// Combine f(FamilyId), m(Model), s(SteppingId) to a single 32 bit number
+///
+#define EfiMakeCpuVersion(f, m, s) (((UINT32) (f) << 16) | ((UINT32) (m) << 8) | ((UINT32) (s)))
+
+#if defined (__GNUC__)
+#define IA32API _EFIAPI
+#else
+#define IA32API __cdecl
+#endif
+
+/**
+ Halt the Cpu
+**/
+VOID
+IA32API
+EfiHalt (
+ VOID
+ );
+
+/**
+ Write back and invalidate the Cpu cache
+**/
+VOID
+IA32API
+EfiWbinvd (
+ VOID
+ );
+
+/**
+ Invalidate the Cpu cache
+**/
+VOID
+IA32API
+EfiInvd (
+ VOID
+ );
+
+/**
+ Get the Cpu info by excute the CPUID instruction
+
+ @param[in] RegisterInEax -The input value to put into register EAX
+ @param[in] Regs -The Output value
+**/
+VOID
+IA32API
+EfiCpuid (
+ IN UINT32 RegisterInEax,
+ OUT EFI_CPUID_REGISTER *Regs
+ );
+
+/**
+ When RegisterInEax != 4, the functionality is the same as EfiCpuid.
+ When RegisterInEax == 4, the function return the deterministic cache
+ parameters by excuting the CPUID instruction
+
+ @param[in] RegisterInEax - The input value to put into register EAX
+ @param[in] CacheLevel - The deterministic cache level
+ @param[in] Regs - The Output value
+**/
+VOID
+IA32API
+EfiCpuidExt (
+ IN UINT32 RegisterInEax,
+ IN UINT32 CacheLevel,
+ OUT EFI_CPUID_REGISTER *Regs
+ );
+
+/**
+ Read Cpu MSR
+
+ @param[in] Index - The index value to select the register
+
+ @retval UINT64 - the read data
+**/
+UINT64
+IA32API
+EfiReadMsr (
+ IN UINT32 Index
+ );
+
+/**
+ Write Cpu MSR
+
+ @param[in] Index - The index value to select the register
+ @param[in] Value - The value to write to the selected register
+**/
+VOID
+IA32API
+EfiWriteMsr (
+ IN UINT32 Index,
+ IN UINT64 Value
+ );
+
+/**
+ Read Time stamp
+
+ @retval Return the read data
+**/
+UINT64
+IA32API
+EfiReadTsc (
+ VOID
+ );
+
+/**
+ Writing back and invalidate the cache,then diable it
+**/
+VOID
+IA32API
+EfiDisableCache (
+ VOID
+ );
+
+/**
+ Invalidate the cache,then Enable it
+**/
+VOID
+IA32API
+EfiEnableCache (
+ VOID
+ );
+
+/**
+ Get Eflags
+
+ @retval Return the Eflags value
+**/
+UINT32
+IA32API
+EfiGetEflags (
+ VOID
+ );
+
+/**
+ Disable interrupt
+**/
+VOID
+IA32API
+EfiDisableInterrupts (
+ VOID
+ );
+/**
+ Enable interrupt
+**/
+VOID
+IA32API
+EfiEnableInterrupts (
+ VOID
+ );
+
+/**
+ Extract CPU detail version infomation
+
+ @param[in] FamilyId - FamilyId, including ExtendedFamilyId
+ @param[in] Model - Model, including ExtendedModel
+ @param[in] SteppingId - SteppingId
+ @param[in] Processor - Processor
+**/
+VOID
+IA32API
+EfiCpuVersion (
+ IN UINT16 *FamilyId,
+ OPTIONAL
+ IN UINT8 *Model,
+ OPTIONAL
+ IN UINT8 *SteppingId,
+ OPTIONAL
+ IN UINT8 *Processor OPTIONAL
+ );
+
+#endif
diff --git a/ReferenceCode/Haswell/Include/CpuDataStruct.h b/ReferenceCode/Haswell/Include/CpuDataStruct.h
new file mode 100644
index 0000000..bb2aee4
--- /dev/null
+++ b/ReferenceCode/Haswell/Include/CpuDataStruct.h
@@ -0,0 +1,142 @@
+/** @file
+ CPU data structure
+
+@copyright
+ Copyright (c) 2004 - 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 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
+**/
+#ifndef _CPU_DATA_STRUCT_H
+#define _CPU_DATA_STRUCT_H
+
+#include EFI_GUID_DEFINITION (SmramCpuDataVariable)
+#include EFI_GUID_DEFINITION (SmramCpuDataHeader)
+
+#pragma pack(1)
+typedef struct {
+ UINT16 Limit;
+ UINTN Base;
+} PSEUDO_DESCRIPTOR;
+#pragma pack()
+
+typedef struct {
+ BOOLEAN APState;
+ BOOLEAN S3BootPath;
+ EFI_PHYSICAL_ADDRESS WakeUpBuffer;
+ EFI_PHYSICAL_ADDRESS GdtrProfile;
+ EFI_PHYSICAL_ADDRESS IdtrProfile;
+ EFI_PHYSICAL_ADDRESS CpuPrivateData;
+ EFI_PHYSICAL_ADDRESS StackAddress;
+ EFI_PHYSICAL_ADDRESS MicrocodePointerBuffer;
+ EFI_PHYSICAL_ADDRESS SmramBase;
+ EFI_PHYSICAL_ADDRESS SmmStartImageBase;
+ UINT32 SmmStartImageSize;
+ UINT32 NumberOfCpus;
+} ACPI_CPU_DATA;
+
+typedef struct {
+ //
+ // Guid as Signature.
+ //
+ EFI_GUID HeaderGuid;
+ EFI_PHYSICAL_ADDRESS AcpiCpuPointer;
+ ACPI_CPU_DATA AcpiCpuData;
+
+ //
+ // It points the data defined below.
+ //
+ EFI_PHYSICAL_ADDRESS GdtrProfileOffset;
+ EFI_PHYSICAL_ADDRESS GdtOffset;
+ EFI_PHYSICAL_ADDRESS IdtrProfileOffset;
+ EFI_PHYSICAL_ADDRESS IdtOffset;
+ EFI_PHYSICAL_ADDRESS CpuPrivateDataOffset;
+ EFI_PHYSICAL_ADDRESS S3BootScriptTableOffset;
+ EFI_PHYSICAL_ADDRESS S3BspMtrrTableOffset;
+ EFI_PHYSICAL_ADDRESS MicrocodePointerBufferOffset; ///< It is pointer to pointer array.
+ EFI_PHYSICAL_ADDRESS MicrocodeDataBufferOffset; ///< It is pointer to the data.
+ ///
+ /// We need put all the data buffer here as well.
+ /// These data will be copied to original location in S3.
+ ///
+ //
+ // DataBuffer size
+ //
+ UINT32 GdtrProfileSize;
+ UINT32 GdtSize;
+ UINT32 IdtrProfileSize;
+ UINT32 IdtSize;
+ UINT32 CpuPrivateDataSize;
+ UINT32 S3BootScriptTableSize;
+ UINT32 S3BspMtrrTableSize;
+ UINT32 MicrocodePointerBufferSize;
+ UINT32 MicrocodeDataBufferSize;
+
+ //
+ // UINT8 WakeUpBufferData[WakeUpBufferSize];
+ // UINT8 GdtrProfileData[GdtrProfileSize];
+ // UINT8 GdtData[GdtSize];
+ // UINT8 IdtrProfileData[IdtrProfileSize];
+ // UINT8 IdtData[IdtSize];
+ // UINT8 CpuPrivateData[CpuPrivateDataSize];
+ // UINT8 S3BootScriptTable[S3BootScriptTableSize];
+ // UINT8 S3BspMtrrTable[S3BspMtrrTableSize];
+ // UINT32 MicrocodePointerBufferData[NumberOfCpus + 1];
+ // UINT8 MicrocodeDataBufferData[MicrocodeDataBufferSize * NumberOfCpus];
+ //
+} SMRAM_CPU_DATA;
+
+typedef struct {
+ UINT32 RegEax;
+ UINT32 RegEbx;
+ UINT32 RegEcx;
+ UINT32 RegEdx;
+} EFI_CPUID_REGISTER;
+
+typedef struct {
+ UINT32 HeaderVersion;
+ UINT32 UpdateRevision;
+ UINT32 Date;
+ UINT32 ProcessorId;
+ UINT32 Checksum;
+ UINT32 LoaderRevision;
+ UINT32 ProcessorFlags;
+ UINT32 DataSize;
+ UINT32 TotalSize;
+ UINT8 Reserved[12];
+} EFI_CPU_MICROCODE_HEADER;
+
+typedef struct {
+ UINT32 ExtendedSignatureCount;
+ UINT32 ExtendedTableChecksum;
+ UINT8 Reserved[12];
+} EFI_CPU_MICROCODE_EXTENDED_TABLE_HEADER;
+
+typedef struct {
+ UINT32 ProcessorSignature;
+ UINT32 ProcessorFlag;
+ UINT32 ProcessorChecksum;
+} EFI_CPU_MICROCODE_EXTENDED_TABLE;
+
+typedef struct {
+ UINT32 Stepping : 4;
+ UINT32 Model : 4;
+ UINT32 Family : 4;
+ UINT32 Type : 2;
+ UINT32 Reserved1 : 2;
+ UINT32 ExtendedModel : 4;
+ UINT32 ExtendedFamily : 8;
+ UINT32 Reserved2 : 4;
+} EFI_CPU_VERSION;
+
+#endif
diff --git a/ReferenceCode/Haswell/Include/CpuPowerMgmt.dsc b/ReferenceCode/Haswell/Include/CpuPowerMgmt.dsc
new file mode 100644
index 0000000..1acb64f
--- /dev/null
+++ b/ReferenceCode/Haswell/Include/CpuPowerMgmt.dsc
@@ -0,0 +1,145 @@
+## @file
+# Build description file for building the power management ACPI tables
+#
+#@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 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
+#
+
+[=============================================================================]
+#
+# Instructions for building the power management ACPI table storage file
+#
+[=============================================================================]
+[Build.Ia32.ACPITABLE,Build.x64.ACPITABLE]
+#
+# Check if we have any source to work with.
+#
+!IFNDEF SECTIONS
+!IFNDEF ASL_FILES
+!ERROR No ASL source files to build were defined in the INF file
+!ENDIF
+!ENDIF
+
+#
+# Define some macros to simplify changes
+#
+TARGET_FFS_FILE = $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).ffs
+
+#
+# Build CST SSDT sections for processor 0
+#
+$(DEST_DIR)\SsdtCpu0Cst.sec : $(ASL_SOURCE_FILES) $(ASL_FILES)
+ $(ASL) $(ASL_FLAGS) $(DEST_DIR)\Ssdt\Cpu0Cst.asl
+ -copy $(DEST_DIR)\Ssdt\Cpu0Cst.aml $(DEST_DIR)\SsdtCpu0Cst.acpi
+ $(GENSECTION) -I $(DEST_DIR)\SsdtCpu0Cst.acpi -O $(DEST_DIR)\SsdtCpu0Cst.sec -S EFI_SECTION_RAW
+
+#
+# Build IST SSDT sections for processor 0
+#
+$(DEST_DIR)\SsdtCpu0Ist.sec : $(ASL_SOURCE_FILES) $(ASL_FILES)
+ $(ASL) $(ASL_FLAGS) $(DEST_DIR)\Ssdt\Cpu0Ist.asl
+ -copy $(DEST_DIR)\Ssdt\Cpu0Ist.aml $(DEST_DIR)\SsdtCpu0Ist.acpi
+ $(GENSECTION) -I $(DEST_DIR)\SsdtCpu0Ist.acpi -O $(DEST_DIR)\SsdtCpu0Ist.sec -S EFI_SECTION_RAW
+
+#
+# Build TST SSDT sections for processor 0
+#
+$(DEST_DIR)\SsdtCpu0Tst.sec : $(ASL_SOURCE_FILES) $(ASL_FILES)
+ $(ASL) $(ASL_FLAGS) $(DEST_DIR)\Ssdt\Cpu0Tst.asl
+ -copy $(DEST_DIR)\Ssdt\Cpu0Tst.aml $(DEST_DIR)\SsdtCpu0Tst.acpi
+ $(GENSECTION) -I $(DEST_DIR)\SsdtCpu0Tst.acpi -O $(DEST_DIR)\SsdtCpu0Tst.sec -S EFI_SECTION_RAW
+
+
+#
+# Build CST SSDT sections for processor 1
+#
+$(DEST_DIR)\SsdtApCst.sec : $(ASL_SOURCE_FILES) $(ASL_FILES)
+ $(ASL) $(ASL_FLAGS) $(DEST_DIR)\Ssdt\ApCst.asl
+ -copy $(DEST_DIR)\Ssdt\ApCst.aml $(DEST_DIR)\SsdtApCst.acpi
+ $(GENSECTION) -I $(DEST_DIR)\SsdtApCst.acpi -O $(DEST_DIR)\SsdtApCst.sec -S EFI_SECTION_RAW
+
+#
+# Build IST SSDT sections for processor 1
+#
+$(DEST_DIR)\SsdtApIst.sec : $(ASL_SOURCE_FILES) $(ASL_FILES)
+ $(ASL) $(ASL_FLAGS) $(DEST_DIR)\Ssdt\ApIst.asl
+ -copy $(DEST_DIR)\Ssdt\ApIst.aml $(DEST_DIR)\SsdtApIst.acpi
+ $(GENSECTION) -I $(DEST_DIR)\SsdtApIst.acpi -O $(DEST_DIR)\SsdtApIst.sec -S EFI_SECTION_RAW
+
+#
+# Build TST SSDT sections for processor 1
+#
+$(DEST_DIR)\SsdtApTst.sec : $(ASL_SOURCE_FILES) $(ASL_FILES)
+ $(ASL) $(ASL_FLAGS) $(DEST_DIR)\Ssdt\ApTst.asl
+ -copy $(DEST_DIR)\Ssdt\ApTst.aml $(DEST_DIR)\SsdtApTst.acpi
+ $(GENSECTION) -I $(DEST_DIR)\SsdtApTst.acpi -O $(DEST_DIR)\SsdtApTst.sec -S EFI_SECTION_RAW
+
+#
+# Build SSDT sections for processor power management
+#
+$(DEST_DIR)\SsdtCpuPm.sec : $(ASL_SOURCE_FILES) $(ASL_FILES)
+ $(ASL) $(ASL_FLAGS) $(DEST_DIR)\Ssdt\CpuPm.asl
+ -copy $(DEST_DIR)\Ssdt\CpuPm.aml $(DEST_DIR)\SsdtCpuPm.acpi
+ $(GENSECTION) -I $(DEST_DIR)\SsdtCpuPm.acpi -O $(DEST_DIR)\SsdtCpuPm.sec -S EFI_SECTION_RAW
+
+#
+# Build SSDT sections for processor power management
+#
+$(DEST_DIR)\SsdtCtdp.sec : $(ASL_SOURCE_FILES) $(ASL_FILES)
+ $(ASL) $(ASL_FLAGS) $(DEST_DIR)\Ssdt\Ctdp.asl
+ -copy $(DEST_DIR)\Ssdt\Ctdp.aml $(DEST_DIR)\SsdtCtdp.acpi
+ $(GENSECTION) -I $(DEST_DIR)\SsdtCtdp.acpi -O $(DEST_DIR)\SsdtCtdp.sec -S EFI_SECTION_RAW
+
+#
+# Build LakeTiny SSDT sections for processor power management
+#
+$(DEST_DIR)\SsdtLakeTiny.sec : $(ASL_SOURCE_FILES) $(ASL_FILES)
+ $(ASL) $(ASL_FLAGS) $(DEST_DIR)\Ssdt\LakeTiny.asl
+ -copy $(DEST_DIR)\Ssdt\LakeTiny.aml $(DEST_DIR)\SsdtLakeTiny.acpi
+ $(GENSECTION) -I $(DEST_DIR)\SsdtLakeTiny.acpi -O $(DEST_DIR)\SsdtLakeTiny.sec -S EFI_SECTION_RAW
+
+#
+# Build FFS file
+#
+$(TARGET_FFS_FILE) : $(SECTIONS) $(DEST_DIR)\SsdtCpu0Cst.sec $(DEST_DIR)\SsdtCpu0Ist.sec $(DEST_DIR)\SsdtCpu0Tst.sec $(DEST_DIR)\SsdtApCst.sec $(DEST_DIR)\SsdtApIst.sec $(DEST_DIR)\SsdtApTst.sec $(DEST_DIR)\SsdtCpuPm.sec $(DEST_DIR)\SsdtCtdp.sec $(DEST_DIR)\SsdtLakeTiny.sec
+ $(GENFFSFILE) -B $(DEST_DIR) -P1 $(DEST_DIR)\$(BASE_NAME).pkg -V
+
+all : $(TARGET_FFS_FILE)
+
+[=============================================================================]
+[Package.ACPITABLE.Default]
+PACKAGE.INF
+\[.]
+BASE_NAME = $(BASE_NAME)
+FFS_FILEGUID = $(FILE_GUID)
+FFS_FILETYPE = EFI_FV_FILETYPE_FREEFORM
+FFS_ATTRIB_CHECKSUM = TRUE
+
+IMAGE_SCRIPT =
+{
+ Compress (Dummy) {
+ $(DEST_DIR)\SsdtCpu0Cst.sec
+ $(DEST_DIR)\SsdtCpu0Ist.sec
+ $(DEST_DIR)\SsdtCpu0Tst.sec
+ $(DEST_DIR)\SsdtApCst.sec
+ $(DEST_DIR)\SsdtApIst.sec
+ $(DEST_DIR)\SsdtApTst.sec
+ $(DEST_DIR)\SsdtCpuPm.sec
+ $(DEST_DIR)\SsdtCtdp.sec
+ $(DEST_DIR)\SsdtLakeTiny.sec
+ }
+}
diff --git a/ReferenceCode/Haswell/Include/CpuRcInclude.cif b/ReferenceCode/Haswell/Include/CpuRcInclude.cif
new file mode 100644
index 0000000..88aff67
--- /dev/null
+++ b/ReferenceCode/Haswell/Include/CpuRcInclude.cif
@@ -0,0 +1,27 @@
+<component>
+ name = "CpuRcInclude"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\Include\"
+ RefName = "CpuRcInclude"
+[files]
+"CommonIncludes.h"
+"CpuAccess.h"
+"CpuBaseLib.h"
+"CpuDataStruct.h"
+"CpuPowerMgmt.dsc"
+"CpuRegs.h"
+"IntelCpuDxe.dsc"
+"IntelCpuDxeLib.dsc"
+"IntelCpuPei.dsc"
+"IntelCpuPeiLib.dsc"
+"PfatDefinitions.h"
+"PowerMgmtDefinitions.h"
+"ThunkLib.h"
+"TisPc.h"
+"Txt.h"
+"Txt.inc"
+"Library\CpuPlatformLib.h"
+"Library\BootGuardLibrary.h"
+"Library\TxtLibrary.h"
+
+<endComponent>
diff --git a/ReferenceCode/Haswell/Include/CpuRegs.h b/ReferenceCode/Haswell/Include/CpuRegs.h
new file mode 100644
index 0000000..ed92b70
--- /dev/null
+++ b/ReferenceCode/Haswell/Include/CpuRegs.h
@@ -0,0 +1,582 @@
+/** @file
+ Conventions:
+ - Prefixes:
+ Definitions beginning with "MSR_" are MSRs
+ Definitions beginning with "R_" are registers
+ Definitions beginning with "B_" are bits within registers
+ Definitions beginning with "V_" are meaningful values of bits within the registers
+ Definitions beginning with "S_" are register sizes
+ Definitions beginning with "N_" are the bit position
+
+@copyright
+ Copyright (c) 2004 - 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 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
+**/
+#ifndef _CPU_REGS_H_
+#define _CPU_REGS_H_
+
+#include "CommonIncludes.h"
+
+//
+// Local APIC defines
+//
+#define APIC_REGISTER_LOCAL_ID_OFFSET 0x00000020
+#define APIC_REGISTER_APIC_VERSION_OFFSET 0x00000030
+#define APIC_REGISTER_SPURIOUS_VECTOR_OFFSET 0x000000F0
+#define APIC_REGISTER_ICR_LOW_OFFSET 0x00000300
+#define APIC_REGISTER_ICR_HIGH_OFFSET 0x00000310
+#define APIC_REGISTER_LINT0_VECTOR_OFFSET 0x00000350
+#define APIC_REGISTER_LINT1_VECTOR_OFFSET 0x00000360
+
+#define BROADCAST_MODE_SPECIFY_CPU 0x00
+#define BROADCAST_MODE_ALL_INCLUDING_SELF 0x01
+#define BROADCAST_MODE_ALL_EXCLUDING_SELF 0x02
+
+#ifndef DELIVERY_MODE_REMOTE_READ
+
+#define DELIVERY_MODE_FIXED 0x00
+#define DELIVERY_MODE_LOWEST_PRIORITY 0x01
+#define DELIVERY_MODE_SMI 0x02
+#define DELIVERY_MODE_REMOTE_READ 0x03
+#define DELIVERY_MODE_NMI 0x04
+#define DELIVERY_MODE_INIT 0x05
+#define DELIVERY_MODE_SIPI 0x06
+#define DELIVERY_MODE_MAX 0x07
+
+#define TRIGGER_MODE_EDGE 0x00
+#define TRIGGER_MODE_LEVEL 0x01
+
+#endif
+
+#define CACHE_UNCACHEABLE 0
+#define CACHE_WRITECOMBINING 1
+#define CACHE_WRITETHROUGH 4
+#define CACHE_WRITEPROTECTED 5
+#define CACHE_WRITEBACK 6
+
+#define CPUID_SIGNATURE 0x0
+#define CPUID_VERSION_INFO 0x1
+#define CPUID_FUNCTION_4 0x4
+#define CPU_CACHE_TYPE_MASK 0x1F
+#define CPU_CACHE_LEVEL_MASK 0x07
+#define CPU_CACHE_ASSOCIATIVITY_MASK 0x03FF
+#define CPU_CACHE_PARTITION_MASK 0x03FF
+#define CPU_CACHE_LINE_SIZE_MASK 0x0FFF
+#define B_CPUID_VERSION_INFO_ECX_MWAIT BIT3
+#define B_CPUID_VERSION_INFO_ECX_VME BIT5
+#define B_CPUID_VERSION_INFO_ECX_SME BIT6
+#define B_CPUID_VERSION_INFO_ECX_EIST BIT7
+#define B_CPUID_VERSION_INFO_ECX_TM2 BIT8
+#define B_CPUID_VERSION_INFO_ECX_DCA BIT18
+#define B_CPUID_VERSION_INFO_ECX_AES BIT25
+#define B_CPUID_VERSION_INFO_ECX_XAPIC BIT21
+#define B_CPUID_VERSION_INFO_EDX_XD BIT20
+#define B_CPUID_VERSION_INFO_EDX_HT BIT28
+#define B_CPUID_VERSION_INFO_EDX_TM1 BIT29
+
+#define CPUID_CACHE_INFO 0x2
+#define CPUID_SERIAL_NUMBER 0x3
+#define CPUID_CACHE_PARAMS 0x4
+
+//
+// CPU ID Instruction defines
+//
+#define V_CPUID_CACHE_TYPE_MASK 0x1F
+#define B_CPUID_CACHE_TYPE_DATA 0x1
+#define B_CPUID_CACHE_TYPE_INSTRUCTION 0x2
+#define B_CPUID_CACHE_TYPE_UNIFIED 0x3
+#define V_CPUID_CACHE_LEVEL_MASK 0xE0
+#define B_CPUID_CACHE_LEVEL_SHIFT 5
+#define B_CPUID_CACHE_PARAMS_WAYS_SHIFT 22
+#define B_CPUID_CACHE_PARAMS_PARTITIONS_SHIFT 12
+#define CPUID_MONITOR_MWAIT_PARAMS 0x5
+#define B_CPUID_MONITOR_MWAIT_ECX_EXTENSIONS BIT0
+#define B_CPUID_MONITOR_MWAIT_EDX_CSTATE BIT0
+#define V_CPUID_MONITOR_MWAIT_EDX_ENHANCED_CSTATE 0x2
+#define CPUID_POWER_MANAGEMENT_PARAMS 0x6
+#define B_CPUID_POWER_MANAGEMENT_EAX_TURBO BIT1
+#define B_CPUID_POWER_MANAGEMENT_EAX_FINE_GRAINED_CLOCK_MODULATION BIT5
+#define B_CPUID_POWER_MANAGEMENT_ECX_ENERGY_EFFICIENT_POLICY_SUPPORT BIT3
+#define CPUID_REV7 0x7
+#define CPUID_REV8 0x8
+#define CPUID_DCA_PARAMS 0x9
+#define CPUID_REVA 0xA
+#define CPUID_CORE_TOPOLOGY 0xB
+#define CPUID_EXTENDED_FUNCTION 0x80000000
+#define CPUID_EXTENDED_CPU_SIG 0x80000001
+#define CPUID_BRAND_STRING1 0x80000002
+#define CPUID_BRAND_STRING2 0x80000003
+#define CPUID_BRAND_STRING3 0x80000004
+#define CPUID_L2_CACHE_FEATURE 0x80000006
+#define CPUID_VIR_PHY_ADDRESS_SIZE 0x80000008
+
+//
+// MSR defines
+//
+#define MSR_IA32_PLATFORM_ID 0x00000017
+#define MSR_IA32_APIC_BASE 0x0000001B
+#define B_MSR_IA32_APIC_BASE_G_XAPIC BIT11
+#define B_MSR_IA32_APIC_BASE_M_XAPIC BIT10
+#define B_MSR_IA32_APIC_BASE_BSP BIT8
+#define PIC_THREAD_CONTROL 0x0000002E
+#define B_PIC_THREAD_CONTROL_TPR_DIS BIT10
+#define MSR_CORE_THREAD_COUNT 0x00000035
+#define N_CORE_COUNT_OFFSET 16
+#define B_THREAD_COUNT_MASK 0xFFFF
+#define MSR_SOCKET_ID_MSR 0x00000039
+#define MSR_IA32_FEATURE_CONTROL 0x0000003A
+#define B_MSR_IA32_FEATURE_CONTROL_LOCK BIT0
+#define B_MSR_IA32_FEATURE_CONTROL_ELT BIT1
+#define B_MSR_IA32_FEATURE_CONTROL_EVT BIT2
+#define B_MSR_IA32_FEATURE_CONTROL_SLFE (BIT8 | BIT9 | BIT10 | BIT11 | BIT12 | BIT13 | BIT14)
+#define B_MSR_IA32_FEATURE_CONTROL_SGE BIT15
+#define MSR_IA32_SMM_SAVE_CONTROL 0x0000003E
+#define B_MSR_IA32_SMM_SAVE_CONTROL_SFPPE BIT0
+#define MSR_IA32_BIOS_UPDT_TRIG 0x00000079
+#define MSR_IA32_BIOS_SIGN_ID 0x0000008B
+#define MSR_IA32_SMM_MONITOR_CONTROL 0x0000009B
+#define MSR_IA32_PMC0_MSR 0x000000C1
+#define MSR_IA32_PMC1_MSR 0x000000C2
+#define MSR_IA32_PMC2_MSR 0x000000C3
+#define MSR_IA32_PMC3_MSR 0x000000C4
+#define MSR_IA32_PMC4_MSR 0x000000C5
+#define MSR_IA32_PMC5_MSR 0x000000C6
+#define MSR_IA32_PMC6_MSR 0x000000C7
+#define MSR_IA32_PMC7_MSR 0x000000C8
+#define MSR_PLATFORM_INFO 0x000000CE
+#define N_PLATFORM_INFO_MIN_RATIO 40
+#define B_PLATFORM_INFO_RATIO_MASK 0xFF
+#define N_PLATFORM_INFO_MAX_RATIO 8
+#define B_MSR_PLATFORM_INFO_PFAT_AVAIL BIT35
+#define N_MSR_PLATFORM_INFO_CONFIG_TDP_NUM_LEVELS_OFFSET 33
+#define V_CONFIG_TDP_NUM_LEVELS_MASK (BIT34 | BIT33)
+#define B_PLATFORM_INFO_TDC_TDP_LIMIT BIT29
+#define N_PLATFORM_INFO_RATIO_LIMIT 28
+#define B_PLATFORM_INFO_RATIO_LIMIT BIT28
+#define B_FIVR_RFI_TUNING_AVAIL BIT25
+#define B_PLATFORM_INFO_SMM_SAVE_CONTROL BIT16
+#define N_PLATFORM_INFO_PROG_TCC_ACTIVATION_OFFSET 30
+#define B_PLATFORM_INFO_PROG_TCC_ACTIVATION_OFFSET BIT30
+#define B_PLATFORM_INFO_TIMED_MWAIT_SUPPORTED BIT37
+#define MSR_PMG_CST_CONFIG 0x000000E2
+#define B_CST_CONTROL_LOCK BIT15
+#define B_IO_MWAIT_REDIRECTION_ENABLE BIT10
+#define B_TIMED_MWAIT_ENABLE BIT31
+#define B_PACKAGE_C_STATE_LIMIT (BIT3 | BIT2 | BIT1 | BIT0)
+#define V_CSTATE_LIMIT_C1 0x01
+#define V_CSTATE_LIMIT_C3 0x02
+#define V_CSTATE_LIMIT_C6 0x03
+#define V_CSTATE_LIMIT_C7 0x04
+#define V_CSTATE_LIMIT_C7S 0x05
+#define V_CSTATE_LIMIT_C8 0x06
+#define V_CSTATE_LIMIT_C9 0x07
+#define V_CSTATE_LIMIT_C10 0x08
+#define B_C3_AUTO_DEMOTION_ENABLE BIT25
+#define B_C1_AUTO_DEMOTION_ENABLE BIT26
+#define B_C3_AUTO_UNDEMOTION_ENABLE BIT27
+#define B_C1_AUTO_UNDEMOTION_ENABLE BIT28
+#define B_PKG_CSTATE_DEMOTION_ENABLE BIT29
+#define B_PKG_CSTATE_UNDEMOTION_ENABLE BIT30
+#define MSR_RFI_TUNNING 0x000000E3
+#define V_FREQ_TUNNING_MASK 0xFFFF
+#define MSR_PMG_IO_CAPTURE_BASE 0x000000E4
+#define B_MSR_PMG_CST_RANGE (BIT18 | BIT17 | BIT16)
+#define V_IO_CAPT_LVL2 (0x0 << 16) ///< C3
+#define V_IO_CAPT_LVL3 (0x1 << 16) ///< C6
+#define V_IO_CAPT_LVL4 (0x2 << 16) ///< C7
+#define V_IO_CAPT_LVL5 (0x3 << 16) ///< C8
+#define V_IO_CAPT_LVL6 (0x4 << 16) ///< C9
+#define V_IO_CAPT_LVL7 (0x5 << 16) ///< C10
+#define V_IO_CAPT_LVL2_BASE_ADDR_MASK 0xFFFF
+#define IA32_MTRR_CAP 0x000000FE
+#define B_IA32_MTRR_VARIABLE_SUPPORT 0xFF
+#define B_IA32_MTRR_CAP_FIXED_SUPPORT BIT8
+#define B_IA32_MTRR_CAP_SMRR_SUPPORT BIT11
+#define B_IA32_MTRR_CAP_EMRR_SUPPORT BIT12
+#define MSR_PLAT_FRMW_PROT_CTRL 0x00000110
+#define B_MSR_PLAT_FRMW_PROT_CTRL_LK BIT0
+#define B_MSR_PLAT_FRMW_PROT_CTRL_EN BIT1
+#define B_MSR_PLAT_FRMW_PROT_CTRL_S1 BIT2
+#define MSR_PLAT_FRMW_PROT_HASH_0 0x00000111
+#define MSR_PLAT_FRMW_PROT_HASH_1 0x00000112
+#define MSR_PLAT_FRMW_PROT_HASH_2 0x00000113
+#define MSR_PLAT_FRMW_PROT_HASH_3 0x00000114
+#define MSR_PLAT_FRMW_PROT_TRIG_PARAM 0x00000115
+#define N_MSR_PLAT_FRMW_PROT_TRIG_PARAM_STATUS_OFFSET 0
+#define V_MSR_PLAT_FRMW_PROT_TRIG_PARAM_STATUS_MASK 0x000000000000FFFF
+#define N_MSR_PLAT_FRMW_PROT_TRIG_PARAM_DATA_OFFSET 16
+#define V_MSR_PLAT_FRMW_PROT_TRIG_PARAM_DATA_MASK 0x000000000000FFFF
+#define N_MSR_PLAT_FRMW_PROT_TRIG_PARAM_TERMINAL_OFFSET 32
+#define V_MSR_PLAT_FRMW_PROT_TRIG_PARAM_TERMINAL_MASK 0x000000000000FFFF
+#define B_MSR_PLAT_FRMW_PROT_TRIG_PARAM_SE BIT62
+#define N_MSR_PLAT_FRMW_PROT_TRIG_PARAM_SE_OFFSET 62
+#define MSR_PLAT_FRMW_PROT_TRIGGER 0x00000116
+#define MSR_PLAT_FRMW_PROT_PASSWD 0x00000117
+#define MSR_SPCL_CHIPSET_USAGE_ADDR 0x000001FE
+#define MSR_IA32_FEATURE_CONFIG 0x0000013C
+#define B_IA32_FEATURE_CONFIG_AES_DIS BIT1
+#define B_IA32_FEATURE_CONFIG_LOCK BIT0
+#define IA32_MCG_CAP 0x00000179
+#define IA32_MCG_STATUS 0x0000017A
+#define MSR_FLEX_RATIO 0x00000194
+#define N_FLEX_RATIO 8
+#define B_FLEX_RATIO (0xFF << 8)
+#define B_FLEX_EN BIT16
+#define B_MAX_EXTRA_VOLTAGE 0xFF
+#define N_OVERCLOCKING_BINS 17
+#define B_OVERCLOCKING_BINS (0x7 << 17)
+#define B_OVERCLOCKING_LOCK BIT20
+#define RATIO_FLEX_CLEAR_MASK 0xFFFFFFFFFFFF00FFULL
+#define MSR_IA32_PERF_STS 0x00000198
+#define N_IA32_PERF_STSP_STATE_TARGET 8
+#define B_IA32_PERF_STSP_STATE_MASK 0xFF
+#define MSR_IA32_PERF_CTRL 0x00000199
+#define N_IA32_PERF_CTRLP_STATE_TARGET 8
+#define B_IA32_PERF_CTRLP_STATE_TARGET (0x7F << 8)
+#define B_IA32_PERF_CTRL_TURBO_DIS BIT32
+#define MSR_IA32_CLOCK_MODULATION 0x0000019A
+#define IA32_THERM_INTERRUPT 0x0000019B
+#define B_IA32_THERM_INTERRUPT_VIE BIT4
+#define MSR_IA32_THERM_STATUS 0x0000019C
+#define MSR_IA32_MISC_ENABLE 0x000001A0
+#define B_MSR_IA32_MISC_ENABLE_FSE BIT0
+#define B_MSR_IA32_MISC_ENABLE_TME BIT3
+#define N_MSR_IA32_MISC_ENABLE_EIST_OFFSET 16
+#define B_MSR_IA32_MISC_ENABLE_EIST BIT16
+#define B_MSR_IA32_MISC_ENABLE_MONITOR BIT18
+#define B_MSR_IA32_MISC_ENABLE_CPUID_MAX BIT22
+#define B_MSR_IA32_MISC_ENABLE_TPR_DIS BIT23
+#define B_MSR_IA32_MISC_ENABLE_XD BIT34
+#define B_MSR_IA32_MISC_DISABLE_TURBO BIT38
+#define MSR_TEMPERATURE_TARGET 0x000001A2
+#define N_MSR_TEMPERATURE_TARGET_TCC_OFFSET_LIMIT 24
+#define N_MSR_TEMPERATURE_TARGET_TCC_ACTIVATION_TEMPERATURE_OFFSET (16)
+#define B_MSR_TEMPERATURE_TARGET_TCC_ACTIVATION_TEMPERATURE_MASK (0xFF << 16)
+#define N_MSR_TEMPERATURE_TARGET_FAN_TEMP_TARGET_OFFSET 8
+#define B_MSR_TEMPERATURE_TARGET_FAN_TEMP_TARGET_OFFSET (0xFF << 8)
+#define MISC_FEATURE_CONTROL 0x000001A4
+#define B_MISC_FEATURE_CONTROL_MLC_STRP BIT0
+#define B_MISC_FEATURE_CONTROL_MLC_SPAP BIT1
+#define B_MISC_FEATURE_CONTROL_DCU_STRP BIT2
+#define B_MISC_FEATURE_CONTROL_DCU_IPP BIT3
+#define MSR_MISC_PWR_MGMT 0x000001AA
+#define B_MSR_MISC_PWR_MGMT_EIST_HW BIT0
+#define B_MSR_MISC_PWR_MGMT_LTMI BIT22
+#define MSR_TURBO_POWER_CURRENT_LIMIT 0x000001AC
+#define B_MSR_TURBO_POWER_CURRENT_LIMIT_TDC_EN BIT31
+#define N_MSR_TURBO_POWER_CURRENT_LIMIT_TDC_LIMIT 16
+#define B_MSR_TURBO_POWER_CURRENT_LIMIT_TDC_LIMIT (0x7F << 16)
+#define B_MSR_TURBO_POWER_CURRENT_LIMIT_TDP_EN BIT15
+#define N_MSR_TURBO_POWER_CURRENT_LIMIT_TDP_LIMIT 0
+#define B_MSR_TURBO_POWER_CURRENT_LIMIT_TDP_LIMIT (0x7F << 0)
+#define MSR_TURBO_RATIO_LIMIT 0x000001AD
+#define N_MSR_TURBO_RATIO_LIMIT_1C 0
+#define B_MSR_TURBO_RATIO_LIMIT_1C (0xFF << 0)
+#define N_MSR_TURBO_RATIO_LIMIT_2C 8
+#define B_MSR_TURBO_RATIO_LIMIT_2C (0xFF << 8)
+#define N_MSR_TURBO_RATIO_LIMIT_3C 16
+#define B_MSR_TURBO_RATIO_LIMIT_3C (0xFF << 16)
+#define N_MSR_TURBO_RATIO_LIMIT_4C 24
+#define B_MSR_TURBO_RATIO_LIMIT_4C (0xFF << 24)
+#define MSR_IA32_ENERGY_PERFORMANCE_BIAS 0x1B0
+#define B_ENERGY_POLICY_MASK 0xF
+#define MSR_IA32_PLATFORM_DCA_CAP 0x000001F8
+#define B_MSR_IA32_PLATFORM_DCA_CAP_TYPE0_EN BIT0
+#define MSR_IA32_CPU_DCA_CAP 0x000001F9
+#define B_MSR_IA32_CPU_DCA_CAP_TYPE0_SUP BIT0
+#define MSR_IA32_DCA_0_CAP 0x000001FA
+#define B_MSR_IA32_CPU_DCA_CAP_ENDID BIT11
+#define N_MSR_IA32_CPU_DCA_CAP_DELAY 13
+#define B_MSR_IA32_CPU_DCA_CAP_DELAY (BIT13 | BIT14 | BIT15 | BIT16)
+#define B_MSR_IA32_CPU_DCA_CAP_SW_LOCK BIT24
+#define B_MSR_IA32_CPU_DCA_CAP_SW_FLUSH BIT25
+#define B_MSR_IA32_CPU_DCA_CAP_HW_LOCK BIT26
+#define MSR_POWER_CTL 0x000001FC
+#define B_MSR_POWER_CTL_BROCHOT BIT0
+#define B_MSR_POWER_CTL_C1E BIT1
+#define B_ENERGY_EFFICIENT_P_STATE_FEATURE_ENABLE BIT18
+#define B_MSR_POWER_CTL_DISABLE_PHOT_OUT BIT21
+#define B_MSR_POWER_CTL_PROC_HOT_RESPONSE BIT22
+#define B_MSR_POWER_CTL_PROC_HOT_LOCK BIT23
+#define B_MSR_POWER_CTL_DISABLE_VR_THERMAL_ALERT BIT24
+#define B_MSR_POWER_CTL_CSTATE_PRE_WAKE_DISABLE BIT30
+#define MSR_FERR_CAPABILITIES 0x000001F1
+#define B_MSR_FERR_ENABLE BIT0
+#define MSR_VR_CURRENT_CONFIG 0x00000601
+#define B_CURRENT_LIMIT_LOCK BIT31
+#define B_CURRENT_LIMIT_MASK 0x1FFF
+#define MSR_VR_MISC_CONFIG 0x603
+#define N_MSR_VR_MISC_CONFIG_MIN_VID_OFFSET 24
+#define B_MSR_VR_MISC_CONFIG_MIN_VID_MASK 0xFF
+#define V_MSR_VR_MISC_CONFIG_MIN_VID_DEFAULT 0
+#define N_MSR_VR_MISC_CONFIG_IDLE_EXIT_RAMP_RATE_OFFSET 50
+#define B_MSR_VR_MISC_CONFIG_IDLE_EXIT_RAMP_RATE BIT50
+#define N_MSR_VR_MISC_CONFIG_IDLE_ENTRY_RAMP_RATE_OFFSET 51
+#define B_MSR_VR_MISC_CONFIG_IDLE_ENTRY_RAMP_RATE BIT51
+#define N_MSR_VR_MISC_CONFIG_IDLE_ENTRY_DECAY_ENABLE_OFFSET 52
+#define B_MSR_VR_MISC_CONFIG_IDLE_ENTRY_DECAY_ENABLE BIT52
+#define N_MSR_VR_MISC_CONFIG_SLOW_SLEW_RATE_CONFIG_OFFSET 53
+#define B_MSR_VR_MISC_CONFIG_SLOW_SLEW_RATE_CONFIG_MASK (BIT54 | BIT53)
+#define V_MSR_VR_MISC_CONFIG_SLOW_SLEW_RATE_CONFIG_DEFAULT 1
+#define V_MSR_VR_MISC_CONFIG_SLOW_SLEW_RATE_CONFIG_FAST_2 0
+#define V_MSR_VR_MISC_CONFIG_SLOW_SLEW_RATE_CONFIG_FAST_4 BIT53
+#define V_MSR_VR_MISC_CONFIG_SLOW_SLEW_RATE_CONFIG_FAST_8 BIT54
+#define V_MSR_VR_MISC_CONFIG_SLOW_SLEW_RATE_CONFIG_FAST_16 (BIT54 | BIT53)
+#define MSR_VR_MISC_CONFIG2 0x636
+#define N_MSR_VR_MISC_CONFIG2_FAST_RAMP_VOLTAGE_OFFSET 0
+#define B_MSR_VR_MISC_CONFIG2_FAST_RAMP_VOLTAGE_MASK 0xFF
+#define V_MSR_VR_MISC_CONFIG2_FAST_RAMP_VOLTAGE_DEFAULT 0x6F
+#define N_MSR_VR_MISC_CONFIG2_MIN_C8_VOLTAGE_OFFSET 8
+#define B_MSR_VR_MISC_CONFIG2_MIN_C8_VOLTAGE_MASK 0xFF
+#define V_MSR_VR_MISC_CONFIG2_MIN_C8_VOLTAGE_DEFAULT 0
+#define MSR_PACKAGE_POWER_SKU_UNIT 0x606
+#define PACKAGE_POWER_UNIT_MASK 0xF
+#define PACKAGE_TIME_UNIT_MASK 0xF0000
+#define MSR_C_STATE_LATENCY_CONTROL_0 0x60A
+#define MSR_C_STATE_LATENCY_CONTROL_1 0x60B
+#define MSR_C_STATE_LATENCY_CONTROL_2 0x60C
+#define MSR_C_STATE_LATENCY_CONTROL_3 0x633
+#define MSR_C_STATE_LATENCY_CONTROL_4 0x634
+#define MSR_C_STATE_LATENCY_CONTROL_5 0x635
+#define B_PKG_IRTL_VALID BIT15
+#define B_INTERRUPT_RESPONSE_TIME_LIMIT_MASK 0x3FF
+#define B_TIME_UNIT_MASK (0x7 << 10)
+#define N_TIME_UNIT_OFFSET 10
+#define MSR_PACKAGE_POWER_LIMIT 0x610
+#define MSR_PACKAGE_POWER_SKU 0x614
+#define B_POWER_LIMIT_ENABLE BIT15
+#define B_CRITICAL_POWER_CLAMP_ENABLE BIT16
+#define B_POWER_LIMIT_LOCK BIT31
+#define POWER_LIMIT_MASK (0x7FFF)
+#define POWER_LIMIT_1_TIME_MASK (0xFE0000)
+#define PACKAGE_TDP_POWER_MASK (0x7FFF)
+#define PACKAGE_MIN_POWER_MASK (0x7FFF0000)
+#define PACKAGE_MAX_POWER_MASK (0x7FFF)
+#define MSR_PLATFORM_POWER_LIMIT 0x615
+#define POWER_LIMIT_3_TIME_MASK (0xFE0000)
+#define POWER_LIMIT_3_DUTY_CYCLE_MASK (0x7F000000)
+#define MSR_DDR_RAPL_LIMIT 0x618
+#define MSR_RING_RATIO_LIMIT 0x620
+#define MSR_MAX_RING_RATIO_LIMIT_MASK 0x7F
+#define MSR_CONFIG_TDP_NOMINAL 0x648
+#define CONFIG_TDP_NOMINAL_RATIO_MASK 0xFF
+#define MSR_CONFIG_TDP_LVL1 0x649
+#define CONFIG_TDP_LVL1_RATIO_OFFSET 16
+#define CONFIG_TDP_LVL1_RATIO_MASK (0xFF << 16)
+#define CONFIG_TDP_LVL1_PKG_TDP_MASK (0x7FFF)
+#define MSR_CONFIG_TDP_LVL2 0x64A
+#define CONFIG_TDP_LVL2_RATIO_OFFSET 16
+#define CONFIG_TDP_LVL2_RATIO_MASK (0xFF << 16)
+#define CONFIG_TDP_LVL2_PKG_TDP_MASK (0x7FFF)
+#define MSR_CONFIG_TDP_CONTROL 0x64B
+#define CONFIG_TDP_CONTROL_LOCK (1 << 31)
+#define CONFIG_TDP_CONTROL_LVL_MASK 0x3
+#define CONFIG_TDP_NOMINAL 0
+#define CONFIG_TDP_LEVEL1 1
+#define CONFIG_TDP_LEVEL2 2
+#define MSR_TURBO_ACTIVATION_RATIO 0x64C
+#define MSR_TURBO_ACTIVATION_RATIO_LOCK (1 << 31)
+#define MSR_TURBO_ACTIVATION_RATIO_MASK 0xFF
+#define SMRR_PHYS_BASE 0x000001F2
+#define SMRR_PHYS_MASK 0x000001F3
+#define EMRR_PHYS_BASE 0x000001F4
+#define EMRR_PHYS_MASK 0x000001F5
+#define B_MSR_EMRR_PHYS_MASK_EN BIT11
+#define B_MSR_EMRR_PHYS_MASK_LOCK BIT10
+#define V_MAXIMUM_VARIABLE_MTRR_NUMBER 10
+#define CACHE_VARIABLE_MTRR_BASE 0x00000200
+#define V_FIXED_MTRR_NUMBER 11
+#define IA32_MTRR_FIX64K_00000 0x00000250
+#define IA32_MTRR_FIX16K_80000 0x00000258
+#define IA32_MTRR_FIX16K_A0000 0x00000259
+#define IA32_MTRR_FIX4K_C0000 0x00000268
+#define IA32_MTRR_FIX4K_C8000 0x00000269
+#define IA32_MTRR_FIX4K_D0000 0x0000026A
+#define IA32_MTRR_FIX4K_D8000 0x0000026B
+#define IA32_MTRR_FIX4K_E0000 0x0000026C
+#define IA32_MTRR_FIX4K_E8000 0x0000026D
+#define IA32_MTRR_FIX4K_F0000 0x0000026E
+#define IA32_MTRR_FIX4K_F8000 0x0000026F
+#define MSR_IA32_CR_PAT 0x00000277
+#define CACHE_IA32_MTRR_DEF_TYPE 0x000002FF
+#define B_CACHE_MTRR_VALID BIT11
+#define B_CACHE_FIXED_MTRR_VALID BIT10
+#define NO_EVICT_MODE 0x000002E0
+#define B_NO_EVICT_MODE_SETUP BIT0
+#define B_NO_EVICT_MODE_RUN BIT1
+#define UNCORE_CR_MEMLOCK_COMMANDS 0x000002E2
+#define B_LOCK_MEM_CFG BIT1
+#define EFI_PCIEXBAR 0x00000300
+#define B_PCIEXBAR_EN BIT0
+#define B_PCIEXBAR_SIZE (BIT1 | BIT2 | BIT3)
+#define N_PCIEXBAR_SIZE 1
+#define IA32_MC0_CTL 0x00000400
+#define IA32_MC0_STATUS 0x00000401
+#define IA32_MC0_ADDR 0x00000402
+#define IA32_MC0_MISC 0x00000403
+#define IA32_MC8_CTL (IA32_MC0_CTL + (8 * 4))
+#define IA32_MC5_STATUS (IA32_MC0_STATUS + (5 * 4))
+#define IA32_MC6_STATUS (IA32_MC0_STATUS + (6 * 4))
+#define IA32_MC7_STATUS (IA32_MC0_STATUS + (7 * 4))
+#define IA32_MC8_STATUS (IA32_MC0_STATUS + (8 * 4))
+#define MSR_IA32_VMX_BASIC 0x00000480
+#define MSR_IA32_VMX_MISC 0x00000485
+#define APIC_GLOBAL_ENABLE 0x00000800
+#define EXT_XAPIC_LOGICAL_APIC_ID 0x00000802
+#define EXT_XAPIC_VERSION 0x00000803
+#define EXT_XAPIC_SVR 0x0000080F
+#define EXT_XAPIC_ICR 0x00000830
+#define MSR_EXT_XAPIC_LVT_THERM 0x00000833
+#define EXT_XAPIC_LVT_LINT0 0x00000835
+#define EXT_XAPIC_LVT_LINT1 0x00000836
+#define MSR_IA32_DEBUG_INTERFACE 0x00000C80
+#define B_DEBUG_INTERFACE_ENABLE BIT0
+#define B_DEBUG_INTERFACE_LOCK BIT30
+#define B_DEBUG_INTERFACE_DEBUG_STATUS BIT31
+#define NUM_TENTHS_TO_PERCENTAGE 1000
+#define FIVR_SSC_LOCK_BIT BIT31
+#define MAX_FIVR_SSC_PERCENT 70
+//
+// MSRs for SMM State Save Register
+//
+#define MSR_SMM_MCA_CAP 0x17D
+#define B_TARGETED_SMI BIT56
+#define N_TARGETED_SMI 56
+#define B_SMM_CPU_SVRSTR BIT57
+#define N_SMM_CPU_SVRSTR 57
+#define B_SMM_CODE_ACCESS_CHK BIT58
+#define N_SMM_CODE_ACCESS_CHK 58
+#define B_LONG_FLOW_INDICATION BIT59
+#define N_LONG_FLOW_INDICATION 59
+#define MSR_SMM_FEATURE_CONTROL 0x4E0
+#define B_SMM_FEATURE_CONTROL_LOCK BIT0
+#define B_SMM_CPU_SAVE_EN BIT1
+#define B_SMM_CODE_CHK_EN BIT2
+#define MSR_SMM_ENABLE 0x4E1
+#define MSR_SMM_DELAYED 0x4E2
+#define MSR_SMM_BLOCKED 0x4E3
+#define MSR_CR0 0xC00
+#define MSR_CR3 0xC01
+#define MSR_EFLAGS 0xC02
+#define MSR_RIP 0xC04
+#define MSR_DR6 0xC05
+#define MSR_DR7 0xC06
+#define MSR_TR_LDTR 0xC07
+#define MSR_GS_FS 0xC08
+#define MSR_DS_SS 0xC09
+#define MSR_CS_ES 0xC0A
+#define MSR_IO_MISC_INFO 0xC0B
+#define MSR_IO_MEM_ADDR 0xC0C
+#define MSR_RDI 0xC0D
+#define MSR_RSI 0xC0E
+#define MSR_RBP 0xC0F
+#define MSR_RSP 0xC10
+#define MSR_RBX 0xC11
+#define MSR_RDX 0xC12
+#define MSR_RCX 0xC13
+#define MSR_RAX 0xC14
+#define MSR_R8 0xC15
+#define MSR_R9 0xC16
+#define MSR_R10 0xC17
+#define MSR_R11 0xC18
+#define MSR_R12 0xC19
+#define MSR_R13 0xC1A
+#define MSR_R14 0xC1B
+#define MSR_R15 0xC1C
+#define MSR_EVENT_CTL_HLT_IO 0xC1F
+#define MSR_SMBASE 0xC20
+#define MSR_SMM_REVID 0xC21
+#define MSR_IEDBASE 0xC22
+#define MSR_EPTP_ENABLE 0xC23
+#define MSR_EPTP 0xC24
+#define MSR_LDTR_BASE 0xC2C
+#define MSR_IDTR_BASE 0xC2D
+#define MSR_GDTR_BASE 0xC2E
+#define MSR_CR4 0xC37
+#define MSR_IO_RSI 0xC40
+#define MSR_IO_RCX 0xC41
+#define MSR_IO_RIP 0xC42
+#define MSR_IO_RDI 0xC43
+#define MSR_BC_PBEC 0x139
+#define B_STOP_PBET BIT0
+
+#define MSR_BOOT_GUARD_SACM_INFO 0x13A
+#define B_NEM_INIT BIT0
+#define V_TPM_PRESENT_MASK 0x06
+#define V_TPM_PRESENT_NO_TPM 0
+#define V_TPM_PRESENT_DTPM_12 1
+#define V_TPM_PRESENT_DTPM_20 2
+#define V_TPM_PRESENT_PTT 3
+#define B_TPM_SUCCESS BIT3
+#define B_MEASURED BIT5
+#define B_VERIFIED BIT6
+#define TXT_PUBLIC_BASE 0xFED30000
+#define R_CPU_BOOT_GUARD_ERRORCODE 0x30
+#define R_CPU_BOOT_GUARD_BOOTSTATUS 0xA0
+#define R_CPU_BOOT_GUARD_ACM_STATUS 0x328
+#define V_CPU_BOOT_GUARD_LOAD_ACM_SUCCESS 0x8000000000000000
+#define B_BOOT_GUARD_ACM_ERRORCODE_MASK 0x00007FF0
+
+//
+// Processor Definitions
+//
+#define CPUID_FULL_STEPPING 0x0000000F
+#define CPUID_FULL_FAMILY_MODEL 0x0FFF0FF0
+#define CPUID_FULL_FAMILY_MODEL_STEPPING 0x0FFF0FFF
+#define CPUID_FULL_FAMILY_MODEL_HASWELL 0x000306C0
+#define CPUID_FULL_FAMILY_MODEL_HASWELL_ULT 0x00040650
+#define CPUID_FULL_FAMILY_MODEL_CRYSTALWELL 0x00040660
+
+#define CPUID_PROCESSOR_TOPOLOGY 0xB
+
+typedef enum {
+ EnumCpuHsw = CPUID_FULL_FAMILY_MODEL_HASWELL,
+ EnumCpuHswUlt = CPUID_FULL_FAMILY_MODEL_HASWELL_ULT,
+ EnumCpuCrw = CPUID_FULL_FAMILY_MODEL_CRYSTALWELL,
+ EnumCpuMax = CPUID_FULL_FAMILY_MODEL
+} CPU_FAMILY;
+
+typedef enum {
+ ///
+ /// Haswell Family Stepping
+ ///
+ EnumHswA0 = 1,
+ EnumHswB0,
+ EnumHswC0,
+ EnumHswD0,
+ ///
+ /// Haswell ULT Family Stepping
+ ///
+ EnumHswUltB0 = 0,
+ EnumHswUltC0,
+ ///
+ /// Crystalwell Family Stepping
+ ///
+ EnumCrwB0 = 0,
+ EnumCrwC0,
+ EnumCrwD0,
+ ///
+ /// Max Stepping
+ ///
+ EnumCpuSteppingMax = CPUID_FULL_STEPPING
+} CPU_STEPPING;
+
+typedef enum {
+ EnumCpuUlt = 0,
+ EnumCpuTrad,
+ EnumCpuUnknown
+} CPU_SKU;
+
+#endif
diff --git a/ReferenceCode/Haswell/Include/IntelCpuDxe.dsc b/ReferenceCode/Haswell/Include/IntelCpuDxe.dsc
new file mode 100644
index 0000000..29cd9a0
--- /dev/null
+++ b/ReferenceCode/Haswell/Include/IntelCpuDxe.dsc
@@ -0,0 +1,53 @@
+## @file
+# Build description file for building the Intel CPU DXE drivers
+#
+#@copyright
+# Copyright (c) 2010 - 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
+#
+
+#
+# CpuInit DXE drivers
+#
+$(PROJECT_CPU_ROOT)\CpuInit\Dxe\CpuInitDxe.inf SOURCE_OVERRIDE_PATH = $(EDK_SOURCE)\Foundation\Library\EdkIIGlueLib\EntryPoints
+
+#
+# DTS SMM drivers
+#
+$(PROJECT_CPU_ROOT)\Dts\Smm\DigitalThermalSensorSmm.inf SOURCE_OVERRIDE_PATH = $(EDK_SOURCE)\Foundation\Library\EdkIIGlueLib\EntryPoints
+
+#
+# PFAT SMM drivers
+#
+$(PROJECT_CPU_ROOT)\Pfat\Smm\PfatServices.inf SOURCE_OVERRIDE_PATH = $(EDK_SOURCE)\Foundation\Library\EdkIIGlueLib\EntryPoints
+
+#
+# Power Management Drivers
+#
+$(PROJECT_CPU_ROOT)\PowerManagement\Dxe\PowerMgmtDxe.inf SOURCE_OVERRIDE_PATH = $(EDK_SOURCE)\Foundation\Library\EdkIIGlueLib\EntryPoints
+$(PROJECT_CPU_ROOT)\PowerManagement\Smm\PowerMgmtS3.inf SOURCE_OVERRIDE_PATH = $(EDK_SOURCE)\Foundation\Library\EdkIIGlueLib\EntryPoints
+$(PROJECT_CPU_ROOT)\PowerManagement\AcpiTables\PowerMgmtAcpiTables.inf
+
+#
+# TxT drivers
+#
+$(PROJECT_CPU_ROOT)\Txt\TxtInit\Dxe\TxtDxe.inf SOURCE_OVERRIDE_PATH = $(EDK_SOURCE)\Foundation\Library\EdkIIGlueLib\EntryPoints
+
+#
+# Sample drivers
+#
+$(PROJECT_CPU_ROOT)\SampleCode\SmramSaveInfoHandlerSmm\SmramSaveInfoHandlerSmm.inf SOURCE_OVERRIDE_PATH = $(EDK_SOURCE)\Foundation\Library\EdkIIGlueLib\EntryPoints
+$(PROJECT_CPU_ROOT)\SampleCode\TxtOneTouch\Dxe\TxtOneTouchDxe.inf SOURCE_OVERRIDE_PATH = $(EDK_SOURCE)\Foundation\Library\EdkIIGlueLib\EntryPoints
+$(PROJECT_CPU_ROOT)\SampleCode\SmmThunk\Smm\SmmThunk.inf SOURCE_OVERRIDE_PATH = $(EDK_SOURCE)\Foundation\Library\EdkIIGlueLib\EntryPoints
+
diff --git a/ReferenceCode/Haswell/Include/IntelCpuDxeLib.dsc b/ReferenceCode/Haswell/Include/IntelCpuDxeLib.dsc
new file mode 100644
index 0000000..3f3faba
--- /dev/null
+++ b/ReferenceCode/Haswell/Include/IntelCpuDxeLib.dsc
@@ -0,0 +1,41 @@
+## @file
+# Build description file for building the CPU DXE libraries
+#
+#@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 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
+#
+
+#
+# CPU DXE Libraries
+#
+$(PROJECT_CPU_ROOT)\Protocol\CpuProtocolLib.inf
+$(PROJECT_CPU_ROOT)\Guid\CpuGuidLib.inf
+$(PROJECT_CPU_ROOT)\Library\Thunklib\Thunklib.inf
+$(PROJECT_CPU_ROOT)\Library\CpuPlatformLib\CpuPlatformLib.inf
+$(PROJECT_CPU_ROOT)\Library\BootGuardLib\BootGuardLib.inf
+
+#
+# DTS DXE Libraries
+#
+$(PROJECT_CPU_ROOT)\SampleCode\Library\SmmIo\SmmIoLib.inf
+$(PROJECT_CPU_ROOT)\SampleCode\Library\AslUpdate\Dxe\DxeAslUpdateLib.inf
+$(PROJECT_CPU_ROOT)\SampleCode\Library\DTSHookLib\Smm\DTSHookLib.inf
+$(PROJECT_CPU_ROOT)\SampleCode\Library\Ksc\Smm\SmmKscLib.inf
+
+#
+# Sample Code
+#
+$(PROJECT_CPU_ROOT)\SampleCode\Protocol\CpuSampleProtocolLib.inf
+$(PROJECT_CPU_ROOT)\SampleCode\Library\BootGuardRevocationLib\Dxe\BootGuardRevocationLib.inf \ No newline at end of file
diff --git a/ReferenceCode/Haswell/Include/IntelCpuPei.dsc b/ReferenceCode/Haswell/Include/IntelCpuPei.dsc
new file mode 100644
index 0000000..98e0c7e
--- /dev/null
+++ b/ReferenceCode/Haswell/Include/IntelCpuPei.dsc
@@ -0,0 +1,35 @@
+## @file
+# Build description file for building the CPU PEI modules
+#
+#@copyright
+# Copyright (c) 2008 - 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
+#
+
+#
+# PEI module produce CPU PPI
+#
+$(PROJECT_CPU_ROOT)\CpuInit\Pei\CpuInitPeim.inf SOURCE_OVERRIDE_PATH = $(EDK_SOURCE)\Foundation\Library\EdkIIGlueLib\EntryPoints
+$(PROJECT_CPU_ROOT)\CpuS3\Pei\CpuS3Peim.inf SOURCE_OVERRIDE_PATH = $(EDK_SOURCE)\Foundation\Library\EdkIIGlueLib\EntryPoints
+
+#
+# TxT Drivers
+#
+$(PROJECT_CPU_ROOT)\Txt\TxtInit\Pei\TxtPei.inf SOURCE_OVERRIDE_PATH = $(EDK_SOURCE)\Foundation\Library\EdkIIGlueLib\EntryPoints
+$(PROJECT_CPU_ROOT)\Txt\TxtInit\Pei\Ia32\TxtPeiApV7.inf
+# $(PROJECT_CPU_ROOT)\Txt\BiosAcm\TxtBiosAcm.inf
+
+#
+# Sample drivers
+#
diff --git a/ReferenceCode/Haswell/Include/IntelCpuPeiLib.dsc b/ReferenceCode/Haswell/Include/IntelCpuPeiLib.dsc
new file mode 100644
index 0000000..a5475e9
--- /dev/null
+++ b/ReferenceCode/Haswell/Include/IntelCpuPeiLib.dsc
@@ -0,0 +1,30 @@
+## @file
+# Build description file for building the CPU PEI Libraries
+#
+#@copyright
+# Copyright (c) 2011 - 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
+#
+
+#
+# CPU PEI libraries
+#
+$(PROJECT_CPU_ROOT)\Ppi\CpuPpiLib.inf
+$(PROJECT_CPU_ROOT)\Guid\CpuGuidLib.inf
+$(PROJECT_CPU_ROOT)\Library\Thunklib\Thunklib.inf
+$(PROJECT_CPU_ROOT)\Library\CpuPlatformLib\CpuPlatformLib.inf
+$(PROJECT_CPU_ROOT)\Library\OverclockingLib\OverClockingLib.inf
+$(PROJECT_CPU_ROOT)\Library\TxtLib\TxtLib.inf
+$(PROJECT_CPU_ROOT)\SampleCode\Library\Ksc\Pei\PeiKscLib.inf
+$(PROJECT_CPU_ROOT)\Library\BootGuardLib\BootGuardLib.inf \ No newline at end of file
diff --git a/ReferenceCode/Haswell/Include/Library/BootGuardLibrary.h b/ReferenceCode/Haswell/Include/Library/BootGuardLibrary.h
new file mode 100644
index 0000000..e6bfbcc
--- /dev/null
+++ b/ReferenceCode/Haswell/Include/Library/BootGuardLibrary.h
@@ -0,0 +1,46 @@
+/** @file
+ Header file for Boot Guard Lib implementation.
+
+@copyright
+ Copyright (c) 2012 - 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 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
+**/
+#ifndef _BOOT_GUARD_LIBRARY_H_
+#define _BOOT_GUARD_LIBRARY_H_
+
+/**
+ Determine if Boot Guard is supported
+
+ @retval TRUE - Processor is Boot Guard capable.
+ @retval FALSE - Processor is not Boot Guard capable.
+
+**/
+BOOLEAN
+IsBootGuardSupported (
+ VOID
+ );
+
+/**
+ Stop PBE timer if system is in Boot Guard boot
+
+ @retval EFI_SUCCESS - Stop PBE timer
+ @retval EFI_UNSUPPORTED - Not in Boot GuardSupport mode.
+**/
+EFI_STATUS
+StopPbeTimer (
+ VOID
+ );
+#endif
diff --git a/ReferenceCode/Haswell/Include/Library/CpuPlatformLib.h b/ReferenceCode/Haswell/Include/Library/CpuPlatformLib.h
new file mode 100644
index 0000000..99b349f
--- /dev/null
+++ b/ReferenceCode/Haswell/Include/Library/CpuPlatformLib.h
@@ -0,0 +1,221 @@
+/** @file
+ Header file for CpuPlatform Lib.
+
+@copyright
+ Copyright (c) 2012 - 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
+**/
+#ifndef _CPU_PLATFORM_LIB_H_
+#define _CPU_PLATFORM_LIB_H_
+
+/**
+ Check CPU Type of the platform
+
+ @retval CPU_FAMILY CPU type
+**/
+CPU_FAMILY
+EFIAPI
+GetCpuFamily (
+ VOID
+ );
+
+/**
+ Return Cpu stepping type
+
+ @retval CPU_STEPPING Cpu stepping type
+**/
+CPU_STEPPING
+EFIAPI
+GetCpuStepping (
+ VOID
+ );
+
+/**
+ Determine if CPU is supported
+
+ @retval TRUE CPU is supported
+ @retval FALSE CPU is not supported
+**/
+BOOLEAN
+IsCpuSupported (
+ VOID
+ );
+
+/**
+ Return CPU Sku
+
+ @retval UINT8 CPU Sku
+**/
+UINT8
+EFIAPI
+GetCpuSku (
+ VOID
+ );
+
+//
+// Mailbox Related Definitions
+//
+#define MAILBOX_TYPE_PCODE 0x00000001
+#define MAILBOX_TYPE_OC 0x00000002
+#define PCODE_MAILBOX_INTERFACE_OFFSET 0x5DA4
+#define PCODE_MAILBOX_DATA_OFFSET 0x5DA0
+#define OC_MAILBOX_MSR 0x00000150
+#define MCHBAR_OFFSET 0x48
+
+//
+// Mailbox commands
+//
+#define READ_ICC_MAX_CMD 0x80002A03
+#define SAMPLE_TSC_24AND100_CMD 0x80000009
+#define READ_TSC24_LOWER_CMD 0x80000109
+#define READ_TSC24_UPPER_CMD 0x80000209
+#define READ_TSC100_LOWER_CMD 0x80000309
+#define READ_TSC100_UPPER_CMD 0x80000409
+#define READ_PCODE_CALIBRATED_CMD 0x80000509
+#define WRITE_CONVERTION_RATIO_CMD 0x80000609
+#define WRITE_PREVENT_BCLKOFF_CMD 0x80000709
+#define WRITE_MEASURE_INTERVAL_CMD 0x80000809
+#define WRITE_FSM_MEASURE_INTVL_CMD 0x80000909
+#define START_CAL_VALUE 0x85000000
+#define READ_PL1_DUTY_CYCLE_CLAMP_ENABLE 0x00000015
+#define WRITE_PL1_DUTY_CYCLE_CLAMP_ENABLE 0x00000016
+#define READ_DDR_FORCE_2X_REFRESH 0x00000017
+#define WRITE_DDR_FORCE_2X_REFRESH 0x00000018
+
+#ifndef MAILBOX_WAIT_TIMEOUT
+#define MAILBOX_WAIT_TIMEOUT 1000 ///< 1 millisecond
+#endif
+#ifndef MAILBOX_WAIT_STALL
+#define MAILBOX_WAIT_STALL 1 ///< 1 microsecond
+#endif
+#ifndef MAILBOX_READ_TIMEOUT
+#define MAILBOX_READ_TIMEOUT 10 ///< 10 microseconds
+#endif
+
+//
+// OC Mailbox Structures
+//
+typedef union _OC_MAILBOX_INTERFACE {
+ UINT32 InterfaceData;
+ struct {
+ UINT8 CommandCompletion : 8;
+ UINT8 Param1 : 8;
+ UINT8 Param2 : 8;
+ UINT8 Reserved : 7;
+ UINT8 RunBusy : 1;
+ } Fields;
+} OC_MAILBOX_INTERFACE;
+
+typedef struct _OC_MAILBOX_FULL {
+ UINT32 Data;
+ OC_MAILBOX_INTERFACE Interface;
+} OC_MAILBOX_FULL;
+
+//
+// OC Mailbox completion codes
+//
+#define OC_MAILBOX_CC_SUCCESS 0
+#define OC_MAILBOX_CC_OC_LOCKED 1
+#define OC_MAILBOX_CC_INVALID_DOMAIN 2
+#define OC_MAILBOX_CC_MAX_RATIO_EXCEEDED 3
+#define OC_MAILBOX_CC_MAX_VOLTAGE_EXCEEDED 4
+#define OC_MAILBOX_CC_OC_NOT_SUPPORTED 5
+
+//
+// PCODE Mailbox Structures
+//
+typedef union _PCODE_MAILBOX_INTERFACE {
+ UINT32 InterfaceData;
+ struct {
+ UINT32 Command : 8;
+ UINT32 Address : 21;
+ UINT32 Reserved : 2;
+ UINT32 RunBusy : 1;
+ } Fields;
+} PCODE_MAILBOX_INTERFACE;
+
+typedef struct _PCODE_MAILBOX_FULL {
+ PCODE_MAILBOX_INTERFACE Interface;
+ UINT32 Data;
+} PCODE_MAILBOX_FULL;
+
+//
+// Pcode Mailbox completion codes
+//
+#define PCODE_MAILBOX_CC_SUCCESS 0
+#define PCODE_MAILBOX_CC_ILLEGAL_CMD 1
+#define PCODE_MAILBOX_CC_TIMEOUT 2
+#define PCODE_MAILBOX_CC_ILLEGAL_DATA 3
+#define PCODE_MAILBOX_CC_RESERVED 4
+#define PCODE_MAILBOX_CC_ILLEGAL_VR_ID 5
+#define PCODE_MAILBOX_CC_VR_INTERFACE_LOCKED 6
+#define PCODE_MAILBOX_CC_VR_ERROR 7
+
+#define READ_PCH_POWER_LEVELS_CMD 0x8000000A
+#define READ_EXT_PCH_POWER_LEVELS_CMD 0x8000000B
+
+EFI_STATUS
+EFIAPI MailboxWrite (
+ IN UINT32 MailboxType,
+ IN UINT32 MailboxCommand,
+ IN UINT32 MailboxData,
+ OUT UINT32 *MailboxStatus
+ )
+/**
+ Generic Mailbox function for mailbox write commands. This function will
+ poll the mailbox interface for control, issue the write request, poll
+ for completion, and verify the write was succussful.
+
+ @param[IN] MailboxType,
+ @param[IN] MailboxCommand,
+ @param[IN] MailboxData,
+ @param[OUT] *MailboxStatus
+
+ @retval EFI_STATUS
+**/
+;
+
+EFI_STATUS
+EFIAPI MailboxRead (
+ IN UINT32 MailboxType,
+ IN UINT32 MailboxCommand,
+ OUT UINT32 *MailboxDataPtr,
+ OUT UINT32 *MailboxStatus
+ )
+/**
+ Generic Mailbox function for mailbox read commands. This function will write
+ the read request, and populate the read results in the output data.
+
+ @param[IN] MailboxType,
+ @param[IN] MailboxCommand,
+ @param[OUT] *MailboxDataPtr,
+ @param[OUT] *MailboxStatus
+
+ @retval EFI_STATUS
+**/
+;
+
+EFI_STATUS
+EFIAPI PollMailboxReady (
+ IN UINT32 MailboxType
+ )
+/**
+ Poll the run/busy bit of the mailbox until available or timeout expires.
+
+ @param[IN] MailboxType,
+
+ @retval EFI_STATUS
+**/
+;
+#endif
diff --git a/ReferenceCode/Haswell/Include/Library/TxtLibrary.h b/ReferenceCode/Haswell/Include/Library/TxtLibrary.h
new file mode 100644
index 0000000..b3f70de
--- /dev/null
+++ b/ReferenceCode/Haswell/Include/Library/TxtLibrary.h
@@ -0,0 +1,44 @@
+/**
+ 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.
+
+@copyright
+ Copyright (c) 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.
+
+@file
+ TxtLibrary.h
+
+@brief
+ Header file for TXT Lib implementation.
+
+**/
+#ifndef _TXT_LIBRARY_H_
+#define _TXT_LIBRARY_H_
+
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueBase.h"
+#endif
+
+UINT32
+CheckSmxCapabilities (
+ VOID
+ )
+/**
+
+ Execute GETSEC[CAPABILITIES] to report the SMX capabilities
+
+**/
+;
+
+#endif
diff --git a/ReferenceCode/Haswell/Include/PfatDefinitions.h b/ReferenceCode/Haswell/Include/PfatDefinitions.h
new file mode 100644
index 0000000..ff1ec9d
--- /dev/null
+++ b/ReferenceCode/Haswell/Include/PfatDefinitions.h
@@ -0,0 +1,328 @@
+/** @file
+ Describes the functions visible to the rest of the PFAT.
+
+@copyright
+ Copyright (c) 2011 - 2014 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
+**/
+#ifndef _PFAT_DEFINITIONS_H_
+#define _PFAT_DEFINITIONS_H_
+
+#ifndef ALIGN_256KB
+#define ALIGN_256KB 0x00040000
+#endif
+#ifndef EFI_PAGE_SIZE
+#define EFI_PAGE_SIZE 0x00001000
+#endif
+
+///
+/// PFAT Module Commands
+///
+#define PFAT_COMMAND_NOP 0x00 ///< NOP
+#define PFAT_COMMAND_BEGIN 0x01 ///< PFAT Begin
+#define PFAT_COMMAND_WRITE_INDEX 0x10 ///< PFAT Write Index
+#define PFAT_COMMAND_WRITE_IMM 0x11 ///< PFAT Write Immediate
+#define PFAT_COMMAND_READ_INDEX 0x12 ///< PFAT Read Index
+#define PFAT_COMMAND_READ_IMM 0x13 ///< PFAT Read Immediate
+#define PFAT_COMMAND_ERASE_BLK 0x14 ///< PFAT Erase Block
+#define PFAT_COMMAND_EC_CMD_WR_INDEX 0x20 ///< EC_CMD Write Index
+#define PFAT_COMMAND_EC_CMD_WR_IMM 0x21 ///< EC_CMD Write Immediate
+#define PFAT_COMMAND_EC_STS_RD 0x22 ///< EC_CMD Read Status
+#define PFAT_COMMAND_EC_DATA_WR_INDEX 0x23 ///< EC_DATA Write Index
+#define PFAT_COMMAND_EC_DATA_WR_IMM 0x24 ///< EC_DATA Write Immediate
+#define PFAT_COMMAND_EC_DATA_RD 0x25 ///< EC_DATA Read
+#define PFAT_COMMAND_SET_BUFFER_INDEX 0x53 ///< PFAT Set Buffer Index
+#define PFAT_COMMAND_SET_FLASH_INDEX 0x55 ///< PFAT Set Flash Index
+#define PFAT_COMMAND_END 0xFF ///< PFAT End
+
+///
+/// PFAT Module Error Codes
+///
+#define ERR_OK 0x0000 ///< Operation completed without error
+#define ERR_UNSUPPORTED_CPU 0x0001 ///< PFAT module detected an incompatibility with the installed CPU
+#define ERR_BAD_DIRECTORY 0x0002 ///< PFAT_DIRECTORY check failed
+#define ERR_BAD_PPDT 0x0003 ///< A pre-execution check of the PPDT failed
+#define ERR_BAD_PUP 0x0004 ///< An inconsistency was found in the update package
+#define ERR_SCRIPT_SYNTAX 0x0005 ///< Unknown operator or name, or invalid syntax found in script
+#define ERR_UNDEFINED_FLASH_OBJECT 0x0006 ///< An unimplemented flash object was referenced
+#define ERR_INVALID_LINE 0x0007 ///< A JMP, JE, JNE, JG, JGE, JL, or JLE operator has a target that is not within the script buffer (between BEGIN and END inclusive)
+#define ERR_BAD_PUPC 0x0008 ///< PUPC inconsistency found
+#define ERR_BAD_SVN 0x0009 ///< PFAT module SVN is lower than required by PPDT
+#define ERR_UNEXPECTED_OPCODE 0x000A ///< An EC related opcode found in a script when the PPDT indicates there is no EC in the system
+#define ERR_RANGE_VIOLATION 0x8001 ///< Buffer or flash operation exceeded object bounds
+#define ERR_SFAM_VIOLATION 0x8002 ///< An unsigned script attempted to write or erase a bock of flash that overlaps with the SFAM
+#define ERR_OVERFLOW 0x8003 ///< An integer overflow occurred
+#define ERR_EXEC_LIMIT 0x8004 ///< Total number of script opcodes retired exceeds either platform limit, or global limit
+#define ERR_INTERNAL_ERROR 0x8005 ///< An internal consistency check failed within the PFAT module
+#define ERR_LAUNCH_FAIL 0xFFFF ///< CPU detected an error and did not execute the PFAT module
+
+#define PFAT_F0_INDEX 0
+#define PFAT_B0_INDEX 0
+
+#define EC_PRESENT BIT1
+#define EC_PFAT_PROTECTED BIT2
+#define PEG_DMI_FIX BIT24;
+
+#define MAX_SPI_COMPONENTS 8
+#define PFAT_MEMORY_PAGES 64 ///< PFAT Module needs 256KB of reserved memory (64 pages of 4KB each one)
+#define ALIGNMENT_IN_PAGES 64 ///< PFAT requires 256KB alignment (64 pages of 4KB each one)
+
+#define PPDT_MAJOR_VERSION 1
+#define PPDT_MINOR_VERSION 0
+#define PFAT_SVN 0x10001
+#define PUP_HDR_VERSION 1
+#define PSL_MAJOR_VERSION 1
+#define PSL_MINOR_VERSION 0
+
+#define PFAT_LOG_VERSION 1
+#define PFAT_LOG_OPT_STEP_TRACE BIT0
+#define PFAT_LOG_OPT_BRANCH_TRACE BIT1
+#define PFAT_LOG_OPT_FLASH_WRITE BIT2
+#define PFAT_LOG_OPT_FLASH_ERASE BIT3
+#define PFAT_LOG_OPT_FLASH_ERROR BIT4
+#define PFAT_LOG_OPT_DEBUG BIT5
+
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+///
+/// GUID to locate PFAT Module
+///
+#define PFAT_MODULE_GUID \
+ { \
+ 0x7934156D, 0xCFCE, 0x460E, 0x92, 0xF5, 0xA0, 0x79, 0x09, 0xA5, 0x9E, 0xCA \
+ }
+///
+/// GUID to locate PFAT HOB
+///
+#define PFAT_HOB_GUID \
+ { \
+ 0x66F0C42D, 0x0D0E, 0x4C23, 0x93, 0xC0, 0x2D, 0x52, 0x95, 0xDC, 0x5E, 0x21 \
+ }
+#else
+///
+/// GUID to locate PFAT Module
+///
+#define PFAT_MODULE_GUID \
+ { \
+ 0x7934156D, 0xCFCE, 0x460E, \
+ { \
+ 0x92, 0xF5, 0xA0, 0x79, 0x09, 0xA5, 0x9E, 0xCA \
+ } \
+ }
+///
+/// GUID to locate PFAT HOB
+///
+#define PFAT_HOB_GUID \
+ { \
+ 0x66F0C42D, 0x0D0E, 0x4C23, \
+ { \
+ 0x93, 0xC0, 0x2D, 0x52, 0x95, 0xDC, 0x5E, 0x21 \
+ } \
+ }
+#endif
+
+#define SPI_SIZE_BASE_512KB 0x80000
+
+typedef enum {
+ EnumSpiCompSize512KB = 0,
+ EnumSpiCompSize1MB,
+ EnumSpiCompSize2MB,
+ EnumSpiCompSize4MB,
+ EnumSpiCompSize8MB,
+ EnumSpiCompSize16MB,
+ EnumSpiCompSize32MB,
+ EnumSpiCompSize64MB,
+ EnumSpiCompSize128MB
+} SPI_COMPONENT_SIZE;
+
+#define MIN_SFAM_COUNT 1
+#define MAX_SFAM_COUNT 64
+
+typedef struct {
+ UINT32 FirstByte; ///< Linear flash address of the first byte of the signed range, must be aligned to be first byte in the block. Ordering is little-endian
+ UINT32 LastByte; ///< Linear flash address of the last byte of the signed range, must be aligned to be last byte in the block. Ordering is little-endian
+} SFAM_DATA;
+
+///
+/// PFAT Platform Data Table (PPDT)
+/// Provides platform specific data required by PFAT Module
+///
+typedef struct {
+ UINT32 PpdtSize; ///< Size in bytes of PPDT including SFAM
+ UINT16 PpdtMajVer; ///< Indicates major version of PPDT
+ UINT16 PpdtMinVer; ///< Indicates minor version of PPDT
+ UINT8 PlatId[16]; ///< PLAT_ID used to be compared against the one found in the PUP Header to prevent cross platform flashing
+ UINT8 PkeySlot0[32]; ///< SHA256 hash for PUP verification key 0
+ UINT8 PkeySlot1[32]; ///< SHA256 hash for PUP verification key 1
+ UINT8 PkeySlot2[32]; ///< SHA256 hash for PUP verification key 2
+ UINT32 PfatModSvn; ///< PFAT Module SVN
+ UINT32 BiosSvn; ///< BIOS_SVN to prevent back-flashing
+ UINT32 ExecLim; ///< Limit the number of opcodes that can be executed on any invocation of PFAT
+ ///
+ /// Bitmap of platform policy attributes
+ /// BIT[0]: Reserved. Must be 0
+ /// BIT[2:1] (EC_PRESENT)
+ /// 00b = There is not an EC is the system
+ /// 01b = There exists an EC in the system, PFAT does not extend any protection to the EC
+ /// 11b = There exist an EC in the system, PFAT extends protection to the EC
+ /// 10b = Reserved. Must not be used
+ /// BIT[3]: (DESCRIPTOR_OVERRIDE_POLICY)
+ /// 0b = Do not override PFAT security policy
+ /// 1b = Override PFAT security policy
+ /// BIT[23:4]: Reserved, must be 0
+ /// BIT[24]:
+ /// 0b = indicates PFAT module will not take additional steps.
+ /// 1b = indicates PFAT module should take additional steps to mitigate potential interference from installed PEG device.
+ /// BIT[31:25] Reserved, must be 0
+ ///
+ UINT32 PlatAttr;
+ ///
+ /// BIT[9:0] - 8 bit IO port used for sending EC commands (writes), and reading EC status (reads)
+ /// This field must be populated if PLAT_ATTR.EC_PRESENT != 0
+ /// This field must be zero if PLAT_ATTR.EC_PRESENT == 0
+ /// BIT[31:10] - Reserved. Must be 0
+ ///
+ UINT32 EcCmd;
+ ///
+ /// BIT[9:0] - 8 bit IO port used for reading and writing data to the EC based on a command issued to EC_CMD
+ /// This field must be populated if PLAT_ATTR.EC_PRESENT != 0
+ /// This field must be zero if PLAT_ATTR.EC_PRESENT == 0
+ /// BIT[31:10] - Reserved. Must be 0
+ ///
+ UINT32 EcData;
+ ///
+ /// BIT[7:0] - EC command indicating a read of the current EC firmware SVN
+ /// This field must be populated if PLAT_ATTR.EC_PRESENT != 0
+ /// This field must be zero if PLAT_ATTR.EC_PRESENT == 0
+ /// BIT[31:8] - Reserved. Must be 0
+ ///
+ UINT32 EcCmdGetSvn;
+ ///
+ /// BIT[7:0] - EC command indicating flash begin of flash update session
+ /// This field must be populated if PLAT_ATTR.EC_PRESENT != 0
+ /// This field must be zero if PLAT_ATTR.EC_PRESENT == 0
+ /// BIT[31:8] - Reserved. Must be 0
+ ///
+ UINT32 EcCmdOpen;
+ ///
+ /// BIT[7:0] - EC command indicating the termination of PFAT protected session
+ /// This field must be populated if PLAT_ATTR.EC_PRESENT != 0
+ /// This field must be zero if PLAT_ATTR.EC_PRESENT == 0
+ /// BIT[31:8] - Reserved. Must be 0
+ ///
+ UINT32 EcCmdClose;
+ ///
+ /// BIT[7:0] - EC command used to verify connectivity between PFAT and EC
+ /// This field must be populated if PLAT_ATTR.EC_PRESENT != 0
+ /// This field must be zero if PLAT_ATTR.EC_PRESENT == 0
+ /// BIT[31:8] - Reserved. Must be 0
+ ///
+ UINT32 EcCmdPortTest;
+ UINT8 Reserved1[4];
+ ///
+ /// Defines number of elements in SFAM array
+ /// BIT[5..0]: Index of the last SFAM element
+ /// BIT[7..6]: Reserved for future use. Must be 0
+ ///
+ UINT8 LastSfam;
+ UINT8 Reserved2[3];
+ SFAM_DATA SfamData[MAX_SFAM_COUNT]; ///< Array of flash address map descriptors. sizeof (SFAM_DESC) == 8
+} PPDT;
+
+///
+/// PFAT Update Package Header
+///
+typedef struct {
+ UINT16 Version; ///< Version of the update package header. Must be 0x0001
+ UINT8 Reserved3[2];
+ UINT8 PlatId[16]; ///< PLAT_ID used to be compared against the one found in the PPDT to prevent cross platform flashing
+ ///
+ /// If any bit set in this field then PUP must be signed and valid PUPC must be provided for PUP to be processed
+ /// BIT[0] - Indicates write/erase operations will be executed on protected flash area indicated in the PPDT SFAM
+ /// BIT[1] - Indicates protected EC operations included
+ ///
+ UINT16 PkgAttributes;
+ UINT8 Reserved4[2];
+ UINT16 PslMajorVer; ///< Indicates the PSL major version. Must be 1
+ UINT16 PslMinorVer; ///< Indicates the PSL minor version. Must be 0
+ UINT32 ScriptSectionSize; ///< Size in bytes of the script
+ UINT32 DataSectionSize; ///< Size of the data region in bytes
+ UINT32 BiosSvn; ///< BIOS SVN
+ UINT32 EcSvn; ///< EC SVN
+ UINT32 VendorSpecific;
+ } PUP_HEADER;
+
+ ///
+ /// Memory location for PUP, PUPC and PFAT LOG inside PFAT DPR allocated memory for Tool interface
+ ///
+#define PUP_BUFFER_SIZE 0x00014000 ///< 16KB Script + 64KB Flash Block
+#define PUPC_MEMORY_SIZE 0x00008000 ///< 32KB
+#define PFAT_LOG_MEMORY_SIZE 0x00020000 ///< 128KB
+#define PUPC_MEMORY_OFFSET (PUPC_MEMORY_SIZE + PFAT_LOG_MEMORY_SIZE) ///< PfatMemAddress + PfatMemSize - PFAT_LOG_MEMORY_SIZE - 32KB
+#define PFAT_LOG_MEMORY_OFFSET PFAT_LOG_MEMORY_SIZE ///< PfatMemAddress + PfatMemSize - 128KB
+#define MAX_PFAT_LOG_PAGE ((PFAT_LOG_MEMORY_SIZE / EFI_PAGE_SIZE) - 2) ///< 30 4KB Pages
+
+ ///
+ /// PFAT update package definition for BIOS SMM Initiated runtime calls
+ ///
+ typedef struct {
+ PUP_HEADER PupHeader;
+ UINT64 PupBuffer[PUP_BUFFER_SIZE / 8];
+ } PUP;
+
+///
+/// PFAT Log
+/// The logging facility is used to communicate detailed information regarding the execution of a PFAT script
+/// from the SMI handler which invoked the PFAT module itself
+///
+typedef struct {
+ UINT16 Version; ///< Indicates the version of the log. Must be 0x0001
+ UINT16 LastPage; ///< Last valid page index for the log
+ ///
+ /// Bitmap indicating what events to log
+ /// BIT[0] - Step trace - this indicates a full execution trace. Each line is entered into the log with an EXECUTION_TRACE entry
+ /// BIT[1] - Branch trace - All taken jumps are logged with a BRANCH_TRACE entry
+ /// BIT[2] - Flash write - All flash write operations are logged with a FLASH_WRITE entry
+ /// BIT[3] - Flash erase - All flash erase operations are logged with a FLASH_ERASE entry
+ /// BIT[4] - Flash error - All error conditions from flash operations are logged with FLASH_ERROR entry
+ /// BIT[5] - Debug - Log Debug opcode execution
+ /// BIT[6] - PFAT module debug message - Log implementation specific debug messages from debug module
+ /// BIT[31:7] - Reserved. Must be 0. If any reserved bits are set in Header.LoggingOptions, the PFAT module must disable the logging feature
+ ///
+ UINT32 LoggingOptions;
+ UINT8 Reserved5[8];
+ UINT32 PfatModSvn; ///< Indicates a version number of the PFAT module
+ UINT32 NumOfEntriesInLog; ///< Total number of log entries that have been written to the log
+} PFAT_LOG;
+
+///
+/// HOB used to pass data through every phase of PFAT Bios
+/// PFAT Bios code is executed in PEI, DXE and SMM and HOB is the only method to properly pass data
+/// between every phase
+///
+typedef struct {
+ EFI_HOB_GUID_TYPE EfiHobGuidType;
+ PPDT Ppdt; ///< PFAT Platform Data Table
+ ///
+ /// PFAT update package header, this header will be appended to all flash updates along with PSL script
+ ///
+ PUP_HEADER PupHeader;
+ UINT8 NumSpiComponents; ///< Number of physical SPI flash components on platform
+ UINT8 ComponentSize[MAX_SPI_COMPONENTS]; ///< Array containing size of each flash component
+ UINT64 PfatToolsIntIoTrapAdd; ///< IO Trap address required to Initialize PFAT Tools Interface
+ PFAT_LOG PfatLog; ///< Header for PFAT Log Buffer
+} PFAT_HOB;
+
+#endif
diff --git a/ReferenceCode/Haswell/Include/PowerMgmtDefinitions.h b/ReferenceCode/Haswell/Include/PowerMgmtDefinitions.h
new file mode 100644
index 0000000..5f95a72
--- /dev/null
+++ b/ReferenceCode/Haswell/Include/PowerMgmtDefinitions.h
@@ -0,0 +1,145 @@
+/** @file
+ This file contains define definitions specific to Haswell processor
+
+@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 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
+**/
+#ifndef _POWER_MGMT_DEFINITIONS_H_
+#define _POWER_MGMT_DEFINITIONS_H_
+
+#define PPM_ENABLE 1
+#define PPM_DISABLE 0
+
+#define CSTATE_SUPPORTED 0x1
+#define ENHANCED_CSTATE_SUPPORTED 0x2
+#define C6_C7_SHORT_LATENCY_SUPPORTED 0x01
+#define C6_C7_LONG_LATENCY_SUPPORTED 0x02
+#define C7s_SHORT_LATENCY_SUPPORTED 0x03
+#define C7s_LONG_LATENCY_SUPPORTED 0x04
+//
+// Platform Power Management Flags Bit Definitions:
+// These defines are also used in CPU0CST.ASL to check platform configuration
+// and build C-state table accordingly.
+//
+#define PPM_EIST 0x1 ///< BIT 0 : Enhanced Intel Speed Step Technology.
+#define PPM_C1 0x2 ///< BIT 1 : C1 enabled, supported.
+#define PPM_C1E 0x4 ///< BIT 2 : C1E enabled.
+#define PPM_C3 0x8 ///< BIT 3 : C3 enabled, supported.
+#define PPM_C6 0x10 ///< BIT 4 : C6 enabled, supported.
+#define PPM_C7 0x20 ///< BIT 5 : C7 enabled, supported.
+#define PPM_C7S 0x40 ///< BIT 6 : C7S enabled, supported
+#define PPM_TM 0x80 ///< BIT 7 : Adaptive Thermal Monitor.
+#define PPM_TURBO 0x100 ///< BIT 8 : Long duration turbo mode
+#define PPM_CMP 0x200 ///< BIT 9 : CMP.
+#define PPM_TSTATES 0x400 ///< BIT 10: CPU throttling states
+#define PPM_MWAIT_EXT 0x800 ///< BIT 11: MONITIOR/MWAIT Extensions supported.
+#define PPM_EEPST 0x1000 ///< BIT 12: Energy efficient P-State Feature enabled
+#define PPM_TSTATE_FINE_GRAINED 0x2000 ///< BIT 13: Fine grained CPU Throttling states
+#define PPM_CD 0x4000 ///< BIT 14: Deep Cstate - C8/C9/C10
+#define PPM_TIMED_MWAIT 0x8000 ///< BIT 15: Timed Mwait support
+#define C6_LONG_LATENCY_ENABLE 0x10000 ///< BIT 16: 1=C6 Long and Short,0=C6 Short only
+#define C7_LONG_LATENCY_ENABLE 0x20000 ///< BIT 17: 1=C7 Long and Short,0=C7 Short only
+#define C7s_LONG_LATENCY_ENABLE 0x40000 ///< BIT 18: 1=C7s Long and Short,0=C7s Short only
+#define PPM_C8 0x80000 ///< Bit 19: 1= C8 enabled/supported
+#define PPM_C9 0x100000 ///< Bit 20: 1= C9 enabled/supported
+#define PPM_C10 0x200000 ///< Bit 21: 1= C10 enabled/supported
+
+#define PPM_C_STATES 0x7A ///< PPM_C1 + PPM_C3 + PPM_C6 + PPM_C7 + PPM_C7S
+#define C3_LATENCY 0x42
+#define C6_C7_SHORT_LATENCY 0x73
+#define C6_C7_LONG_LATENCY 0x91
+#define C8_LATENCY 0xE4
+#define C9_LATENCY 0x145
+#define C10_LATENCY 0x1EF
+
+#define CPUID_FUNCTION_6 0x00000006
+//
+// The following definitions are based on assumed location for the ACPI
+// Base Address. Modify as necessary base on platform-specific requirements.
+//
+#define PCH_ACPI_PBLK 0x1810
+#define PCH_ACPI_LV2 0x1814
+#define PCH_ACPI_LV3 0x1815
+#define PCH_ACPI_LV4 0x1816
+#define PCH_ACPI_LV6 0x1818
+#define PCH_ACPI_LV5 0x1817
+#define PCH_ACPI_LV7 0x1819
+
+//
+// C-State Latency (us) and Power (mW) for C1
+//
+#define C1_LATENCY 1
+#define C1_POWER 0x3E8
+#define C3_POWER 0x1F4
+#define C6_POWER 0x15E
+#define C7_POWER 0xC8
+#define C8_POWER 0xC8
+#define C9_POWER 0xC8
+#define C10_POWER 0xC8
+
+#define MAX_POWER_LIMIT_1_TIME_IN_SECONDS 32767
+#define AUTO 0
+#define END_OF_TABLE 0xFF
+
+#define CONFIG_TDP_DOWN 1
+#define CONFIG_TDP_UP 2
+#define CONFIG_TDP_DEACTIVATE 0xFF
+//
+// MMIO definitions
+//
+#define MMIO_DDR_RAPL_LIMIT 0x58e0
+#define MMIO_TURBO_POWER_LIMIT 0x59A0
+
+#define MAX_OVERCLOCKING_BINS 0x7
+
+///
+/// For Mobile, default PL1 time window value is 28 seconds
+///
+#define MB_POWER_LIMIT1_TIME_DEFAULT 28
+///
+/// For Desktop, default PL1 time window value is 8 second
+///
+#define DT_POWER_LIMIT1_TIME_DEFAULT 8
+
+#define PROCESSOR_FLAVOR_MOBILE 0x04
+#define PROCESSOR_FLAVOR_DESKTOP 0x00
+#define PROCESSOR_FLAVOR_MASK (BIT3 | BIT2)
+
+//
+// Power definitions (Based on EMTS V1.0 for standard voltage 2.4-2.6 GHz dual-core parts.)
+//
+#define FVID_MAX_POWER 35000
+#define FVID_TURBO_POWER 35000
+#define FVID_SUPERLFM_POWER 12000
+//
+// Power definitions for LFM and Turbo mode TBD.
+//
+#define FVID_MIN_POWER 15000
+///
+/// S3- MSR restore SW SMI
+///
+#ifndef SW_SMI_S3_RESTORE_MSR
+#define SW_SMI_S3_RESTORE_MSR 0x48
+#endif
+///
+/// VR Current Limit Default
+///
+#define VR_CURRENT_DEFAULT 0
+#define PSI1_THRESHOLD_DEFAULT 0x14
+#define PSI2_THRESHOLD_DEFAULT 0x05
+#define PSI3_THRESHOLD_DEFAULT 0x01
+#endif
diff --git a/ReferenceCode/Haswell/Include/ThunkLib.h b/ReferenceCode/Haswell/Include/ThunkLib.h
new file mode 100644
index 0000000..8d7146a
--- /dev/null
+++ b/ReferenceCode/Haswell/Include/ThunkLib.h
@@ -0,0 +1,154 @@
+/** @file
+ Real Mode Thunk Functions for IA32 and X64
+
+@copyright
+ Copyright (c) 2006 - 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
+**/
+#ifndef __THUNK_LIB__
+#define __THUNK_LIB__
+
+///
+/// Byte packed structure for an 16-bit real mode thunks
+///
+typedef struct {
+ UINT32 RealModeBuffer;
+ UINT32 DefaultStack;
+} THUNK16_CONTEXT;
+
+//
+// 16-bit thunking services
+//
+#define THUNK_SAVE_FP_STATE 0x1
+#define THUNK_USER_STACK 0x2
+#define THUNK_INTERRUPT 0x10000
+
+//
+// Function Prototypes
+//
+/**
+ Returns the properties of this real mode thunk implementation. Currently
+ there are 2 properties has been defined, the minimum real mode buffer size
+ and the minimum stack size.
+
+ @param[in] MinimumStackSize - The minimum size required for a 16-bit stack.
+
+ @retval The minimum size of the real mode buffer needed by this thunk implementation
+ @retval is returned.
+**/
+UINTN
+EFIAPI
+R8AsmThunk16GetProperties (
+ OUT UINTN *MinimumStackSize OPTIONAL
+ );
+
+/**
+ Tell this real mode thunk implementation the address and size of the real
+ mode buffer needed.
+
+ @param[in] ThunkContext - The thunk context whose properties to set.
+ @param[in] RealModeBuffer - The address of the buffer allocated by caller. It should be
+ aligned on a 16-byte boundary.
+ This buffer must be in identity mapped pages.
+ @param[in] BufferSize - The size of RealModeBuffer. Must be larger than the minimum
+ size required as returned by R8AsmThunk16GetProperties().
+**/
+THUNK16_CONTEXT *
+EFIAPI
+R8AsmThunk16SetProperties (
+ OUT THUNK16_CONTEXT *ThunkContext,
+ IN VOID *RealModeBuffer,
+ IN UINTN BufferSize
+ );
+
+/**
+ Reset all internal states to their initial values. The caller should not
+ release the real mode buffer until after a call to this function.
+
+ @param[in] ThunkContext - The thunk context to destroy.
+**/
+VOID
+EFIAPI
+R8AsmThunk16Destroy (
+ IN OUT THUNK16_CONTEXT *ThunkContext
+ );
+
+/**
+ Make a far call to 16-bit code.
+
+ NOTE: This function must be called on TPL_HIGH_LEVEL or with interrupts
+ disabled because of GDTR and IDTR manipulations.
+ This function must be placed in identity mapped pages.
+
+ @param[in] ThunkContext - Thunk context to use.
+ @param[in] RegisterSet - CPU registers would be set to the values contained in this
+ structure before making the far call. Then CPU registers are
+ copied back to this structure.
+ CS:EIP points to the real mode code being called on input.
+ SS:ESP points to the real mode stack if THUNK_USER_STACK is
+ set on input, otherwise ignored.
+ EFlages is ignored on input.
+ On output, values of CS, EIP, SS and ESP should be ignored.
+ @param[in] ThunkFlags - 2 flags have currently been defined, THUNK_SAVE_FP_STATE and
+ THUNK_USER_STACK.
+ THUNK_SAVE_FP_STATE - FPU state would be saved/restored
+ before/after calling real mode code.
+ THUNK_USER_STACK - The stack specified by SS:ESP would be
+ used instead of the default stack.
+
+ @retval RegisterSet is returned.
+**/
+IA32_REGISTER_SET *
+EFIAPI
+R8AsmThunk16FarCall86 (
+ IN THUNK16_CONTEXT *ThunkContext,
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 ThunkFlags
+ );
+
+/**
+ Invoke a 16-bit interrupt handler.
+
+ NOTE: This function must be called on TPL_HIGH_LEVEL or with interrupts
+ disabled because of GDTR and IDTR manipulations.
+ This function must be placed in identity mapped pages.
+
+ @param[in] ThunkContext - Thunk context to use.
+ @param[in] IntNumber - The ordinal of the interrupt handler ranging from 0 to 255.
+ @param[in] RegisterSet - CPU registers would be set to the values contained in this
+ structure before making the far call. Then CPU registers are
+ copied back to this structure.
+ SS:ESP points to the real mode stack if THUNK_USER_STACK is
+ set on input, otherwise ignored.
+ EFlages is ignored on input.
+ On output, values of CS, EIP, SS and ESP should be ignored.
+ @param[in] ThunkFlags - 2 flags have currently been defined, THUNK_SAVE_FP_STATE and
+ THUNK_USER_STACK.
+ THUNK_SAVE_FP_STATE - FPU state would be saved/restored
+ before/after calling real mode code.
+ THUNK_USER_STACK - The stack specified by SS:ESP would be
+ used instead of the default stack.
+
+ @retval RegisterSet is returned.
+**/
+IA32_REGISTER_SET *
+EFIAPI
+R8AsmThunk16Int86 (
+ IN THUNK16_CONTEXT *ThunkContext,
+ IN UINT8 IntNumber,
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 ThunkFlags
+ );
+
+#endif
diff --git a/ReferenceCode/Haswell/Include/TisPc.h b/ReferenceCode/Haswell/Include/TisPc.h
new file mode 100644
index 0000000..e11434b
--- /dev/null
+++ b/ReferenceCode/Haswell/Include/TisPc.h
@@ -0,0 +1,71 @@
+/**
+ 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
+
+@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.
+
+@file
+ TisPc.h
+
+@brief
+ Definitions and function prototypes shared by all TPM components
+
+**/
+#ifndef _TIS_PC_H_
+#define _TIS_PC_H_
+
+///
+/// Set structure alignment to 1-byte
+///
+#pragma pack(push)
+#pragma pack(1)
+///
+/// TPM Base Address Definitions
+///
+#define TPM_BASE_ADDRESS 0xFED40000
+///
+/// Register set map as specified in TIS Chapter 10
+///
+typedef struct tdTIS_PC_REGISTERS {
+ INT8 access; ///< 0
+ UINT8 reserved1[7]; ///< 1
+ UINT32 intEnable; ///< 8
+ UINT8 intVector; ///< 0ch
+ UINT8 reserved2[3]; ///< 0dh
+ UINT32 intSts; ///< 10h
+ UINT32 intfCapability; ///< 14h
+ INT8 status; ///< 18h
+ UINT16 burstCount; ///< 19h
+ UINT8 reserved3[9];
+ UINT32 dataFifo; ///< 24
+ UINT8 reserved4[0xed8]; ///< 28h
+ UINT16 vid; ///< 0f00h
+ UINT16 did; ///< 0f02h
+ UINT8 rid; ///< 0f04h
+ UINT8 tcgDefined[0x7b]; ///< 0f05h
+ UINT32 legacyAddress1; ///< 0f80h
+ UINT32 legacyAddress1Ex; ///< 0f84h
+ UINT32 legacyAddress2; ///< 0f88h
+ UINT32 legacyAddress2Ex; ///< 0f8ch
+ UINT8 vendorDefined[0x70]; ///< 0f90h
+} TIS_PC_REGISTERS;
+
+///
+/// Define pointer types used to access TIS registers on PC
+///
+typedef VOLATILE TIS_PC_REGISTERS *TIS_PC_REGISTERS_PTR;
+
+#pragma pack(pop)
+#endif
diff --git a/ReferenceCode/Haswell/Include/Txt.h b/ReferenceCode/Haswell/Include/Txt.h
new file mode 100644
index 0000000..5db5155
--- /dev/null
+++ b/ReferenceCode/Haswell/Include/Txt.h
@@ -0,0 +1,160 @@
+/** @file
+ This file contains definitions required to use the TXT BIOS
+ Authenticated Code Module Library.
+
+@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 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
+**/
+#ifndef _TXT_BIOS_ACM_LIB_H_
+#define _TXT_BIOS_ACM_LIB_H_
+
+#define TPM_TIME_OUT 750
+
+#define TXT_RLP_INIT 1
+
+///
+/// MMIO definition
+///
+#ifndef MmPciAddress
+//#define MmPciAddress(Segment, Bus, Device, Function, Register) \
+// ((UINTN) (PciRead32 (PCI_LIB_ADDRESS (0,0,0,0x60)) & 0xFC000000) + \
+// (UINTN) (Bus << 20) + \
+// (UINTN) (Device << 15) + \
+// (UINTN) (Function << 12) + \
+// (UINTN) (Register) \
+// )
+#define MmPciAddress(Segment, Bus, Device, Function, Register) \
+ ((UINTN) PlatformPciExpressBaseAddress + \
+ (UINTN) (Bus << 20) + \
+ (UINTN) (Device << 15) + \
+ (UINTN) (Function << 12) + \
+ (UINTN) (Register) \
+ )
+#endif
+//
+// TxT BIOS Spec version
+//
+#define TXT_BIOS_SPEC_VER_MAJOR 2
+#define TXT_BIOS_SPEC_VER_MINOR 1
+#define TXT_BIOS_SPEC_VER_REVISION 0
+
+//
+// The following are values that are placed in the esi register when
+// calling the BIOS ACM. These constants are used as parameters to the
+// TxtSetupandLaunchBiosAcm function.
+//
+#define TXT_LAUNCH_SCLEAN 0x00
+#define TXT_RESET_EST_BIT 0x01
+#define TXT_RESET_AUX 0x02
+#define TXT_LAUNCH_SCHECK 0x04
+
+#define TPM_STATUS_REG_ADDRESS 0xFED40000
+#define TXT_PUBLIC_BASE 0xFED30000
+#define TXT_PRIVATE_BASE 0xFED20000
+#define TXT_CONFIG_SPACE_LENGTH 0x60000
+
+#define TXT_ERROR_STATUS_REG_OFF 0x8
+#define TXT_SINIT_BASE_REG_OFF 0x270
+#define TXT_SINIT_SIZE_REG_OFF 0x278
+#define TXT_SINIT_SIZE_REG_OFF2 0x27C
+#define TXT_SVMM_JOIN_REG_OFF 0x290
+#define TXT_SVMM_JOIN_REG_OFF2 0x294
+#define TXT_HEAP_BASE_REG_OFF 0x300
+#define TXT_HEAP_SIZE_REG_OFF 0x308
+#define TXT_SCRATCHPAD 0x320
+#define TXT_SCRATCHPAD2 0x324
+#define TXT_SCRATCHPAD3 0x328
+#define TXT_SCRATCHPAD4 0x32C
+#define TXT_DPR_SIZE_REG_OFF 0x330
+
+#define TXT_E2STS_REG_OFF 0x8F0
+#define TXT_BLOCK_MEM_STS BIT2
+#define TXT_SECRETS_STS BIT1
+#define TXT_SLP_ENTRY_ERROR_STS BIT0
+
+#define MCU_BASE_ADDR TXT_SINIT_SIZE_REG_OFF
+#define BIOACM_ADDR TXT_SINIT_SIZE_REG_OFF2
+#define APINIT_ADDR TXT_SVMM_JOIN_REG_OFF
+#define SEMAPHORE TXT_SVMM_JOIN_REG_OFF2
+
+///
+/// GUIDs used by TXT drivers
+///
+#define PEI_BIOS_ACM_FILE_GUID \
+ { \
+ 0x2D27C618, 0x7DCD, 0x41F5, 0xBB, 0x10, 0x21, 0x16, 0x6B, 0xE7, 0xE1, 0x43 \
+ }
+
+#define PEI_AP_STARTUP_FILE_GUID \
+ { \
+ 0xD1E59F50, 0xE8C3, 0x4545, 0xBF, 0x61, 0x11, 0xF0, 0x02, 0x23, 0x3C, 0x97 \
+ }
+
+#define CPU_MICROCODE_FILE_GUID \
+ { \
+ 0x17088572, 0x377F, 0x44ef, 0x8F, 0x4E, 0xB0, 0x9F, 0xFF, 0x46, 0xA0, 0x70 \
+ }
+
+#pragma pack(push, 1)
+///
+/// BIOS OS Data region definitions
+///
+#define BIOS_OS_DATAREGION_VERSION 4
+
+typedef struct {
+ UINT32 Type;
+ UINT32 Size;
+} HEAP_EXT_DATA_ELEMENT;
+
+///
+/// BIOS spec version element
+///
+#define HEAP_EXTDATA_TYPE_BIOS_SPEC_VER 1
+
+typedef struct {
+ HEAP_EXT_DATA_ELEMENT Header;
+ UINT16 SpecVerMajor;
+ UINT16 SpecVerMinor;
+ UINT16 SpecVerRevision;
+} HEAP_BIOS_SPEC_VER_ELEMENT;
+
+///
+/// BIOS ACM element
+///
+#define HEAP_EXTDATA_TYPE_BIOSACM 2
+typedef struct {
+ HEAP_EXT_DATA_ELEMENT Header;
+ UINT32 NumAcms;
+} HEAP_BIOSACM_ELEMENT;
+
+///
+/// END type
+///
+#define HEAP_EXTDATA_TYPE_END 0
+
+typedef struct {
+ UINT32 Version;
+ UINT32 BiosSinitSize;
+ EFI_PHYSICAL_ADDRESS LcpPdBase;
+ UINT64 LcpPdSize;
+ UINT32 NumOfLogicalProcessors;
+ UINT64 Flags;
+ HEAP_EXT_DATA_ELEMENT ExtData;
+} BIOS_OS_DATA_REGION;
+
+#pragma pack(pop)
+#endif
diff --git a/ReferenceCode/Haswell/Include/Txt.inc b/ReferenceCode/Haswell/Include/Txt.inc
new file mode 100644
index 0000000..4cd76fe
--- /dev/null
+++ b/ReferenceCode/Haswell/Include/Txt.inc
@@ -0,0 +1,442 @@
+;@file
+; This file contains definitions used in Txtpeibsp and txtpeiap.asm
+;
+;@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 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
+;
+
+;-----------------------------------------------------------------------------
+; Common equates
+;
+
+UINT32 TYPEDEF DWORD
+UINT64 TYPEDEF QWORD
+
+;-----------------------------------------------------------------------------
+; Bit definitions
+;
+BIT31 EQU (1 SHL 31)
+BIT30 EQU (1 SHL 30)
+BIT29 EQU (1 SHL 29)
+BIT28 EQU (1 SHL 28)
+BIT27 EQU (1 SHL 27)
+BIT26 EQU (1 SHL 26)
+BIT25 EQU (1 SHL 25)
+BIT24 EQU (1 SHL 24)
+BIT23 EQU (1 SHL 23)
+BIT22 EQU (1 SHL 22)
+BIT21 EQU (1 SHL 21)
+BIT20 EQU (1 SHL 20)
+BIT19 EQU (1 SHL 19)
+BIT18 EQU (1 SHL 18)
+BIT17 EQU (1 SHL 17)
+BIT16 EQU (1 SHL 16)
+BIT15 EQU (1 SHL 15)
+BIT14 EQU (1 SHL 14)
+BIT13 EQU (1 SHL 13)
+BIT12 EQU (1 SHL 12)
+BIT11 EQU (1 SHL 11)
+BIT10 EQU (1 SHL 10)
+BIT9 EQU (1 SHL 9)
+BIT8 EQU (1 SHL 8)
+BIT7 EQU (1 SHL 7)
+BIT6 EQU (1 SHL 6)
+BIT5 EQU (1 SHL 5)
+BIT4 EQU (1 SHL 4)
+BIT3 EQU (1 SHL 3)
+BIT2 EQU (1 SHL 2)
+BIT1 EQU (1 SHL 1)
+BIT0 EQU (1 SHL 0)
+
+PORTB EQU 061h
+PORTBMASK EQU (1 shl 4)
+;
+; BIOS ACM functions
+;
+TXT_LAUNCH_SCLEAN EQU 00h
+TXT_RESET_EST_BIT EQU 01h
+TXT_RESET_AUX EQU 02h
+TXT_LAUNCH_SCHECK EQU 04h
+
+PORT80_CODE_PREFIX EQU 0A0h
+
+;
+; EDI parameter sent to SCHECK function
+;
+COLD_BOOT_PATH EQU 0
+S3_RESUME_PATH EQU BIT1
+;----------------------------------------------------------------------------
+; Common stackless calling macros
+;
+CALL_NS MACRO lbl
+ local retaddr
+ if @WordSize EQ 2
+ mov sp, retaddr
+ else
+ mov esp, retaddr
+ endif
+
+ pslldq xmm4, 4
+ pinsrw xmm4, esp, 0
+ rol esp, 10h
+ pinsrw xmm4, esp, 1
+
+ jmp lbl
+
+retaddr:
+ENDM
+
+RET_NS MACRO
+ movd esp, xmm4
+ psrldq xmm4, 4
+
+ if @WordSize EQ 2
+ jmp sp
+ else
+ jmp esp
+ endif
+ENDM
+
+;-----------------------------------------------------------------------------
+; AC Module header
+;
+ACM_HEADER STRUCT
+ ORG 24
+ AcmSize dd ? ; // 24 4 Module size (in multiples of four bytes)
+ACM_HEADER ENDS
+
+;-----------------------------------------------------------------------------
+; TXT enabling and execution
+;
+
+CAPABILITIES EQU 00h
+ENTERACCS EQU 02h
+
+CR0_NE_MASK EQU (1 SHL 5)
+CR0_NW_MASK EQU (1 SHL 29)
+CR0_CD_MASK EQU (1 SHL 30)
+CR0_PG_MASK EQU (1 SHL 31)
+
+CR4_VME EQU (1 SHL 0)
+CR4_PVI EQU (1 SHL 1)
+CR4_TSD EQU (1 SHL 2)
+CR4_DE EQU (1 SHL 3)
+CR4_PSE EQU (1 SHL 4)
+CR4_PAE EQU (1 SHL 5)
+CR4_MSE EQU (1 SHL 6)
+CR4_PGE EQU (1 SHL 7)
+CR4_PCE EQU (1 SHL 8)
+CR4_OSFXSR EQU (1 SHL 9)
+CR4_VMXE EQU (1 SHL 13)
+CR4_SMXE EQU (1 SHL 14)
+
+_GETSEC EQU db 0fh, 37h
+
+;----------------------------------------------------------------------------
+; DescriptorAccess Rights Definitions
+;
+PAGEGRANULARITY EQU 01H ; Page Granularity
+BYTEGRANULARITY EQU 00H ; Byte Granularity
+BIGSEGMENT EQU 01H ; Big Segment 32 bit
+SMALLSEGMENT EQU 00H ; Small Segment 16 bit
+SEG_PRESENT EQU 01H ; Segment Present
+SEG_NOTPRESENT EQU 00H ; Segment Not Present
+APPLSEGMENT EQU 01H ; Application Segment
+SYSTEMSEGMENT EQU 00H ; System Segment
+
+DATATYPE EQU 03H ; Read, Write, accessed
+STACKTYPE EQU 03H ; Read, Write, accessed
+CODETYPE EQU 0BH ; Execute, Read, accessed
+
+;----------------------------------------------------------------------------
+;Descritor table structures and records
+;
+
+R_AR0_7 RECORD P:1=0, DPL:2=0, D_T:1=0, sType:4=0
+
+; P - Segment present
+; 0=NOTPRESENT
+; 1=PRESENT
+; DPL - Descriptor priviledge level
+; D_T - Descriptor type
+; 0=SYSTEMSEGMENT
+; 1=APPLSEGMENT
+; sType - Segment Type
+; For Application segment:
+; 03h - DATATYPE (Read/Write/Accessed)
+; 07h - STACKTYPE (Expand Down/Read/Write/Accessed)
+; 0Fh - CODETYPE (Execute/Conforming/Read/Accessed)
+;
+; For System segment:
+; 01h - Available 16 bit TSS
+; 02h - LDT
+; 03h - Active 16 bit TSS
+; 04h - 16 bit call gate
+; 05h - 16 + 32 bit task gate
+; 06h - 16 bit interrupt gate
+; 07h - 16 bit trap gate
+; 09h - Available 32 bit TSS
+; 0Bh - Active 32 bit TSS
+; 0Ch - 32 bit call gate
+; 0Eh - 32 bit interrupt gate
+; 0Fh - 32 bit trap gate
+
+R_LAR16_23 RECORD G:1=0, D_B:1=0, L:1=0, Avl:1=0, Lim:4=0
+
+; G - Granularity
+; 0=BYTEGRANULARITY
+; 1=PAGEGRANULARITY
+; D_B - Segment size
+; 0=SMALLSEGMENT
+; 1=BIGSEGMENT
+; Res - Reserved
+; Avl - Available for OS (Not used)
+; Lim - Limit bits 16-19
+
+SEG_DESCRIPTOR STRUCT 4
+ Limit0_15 DW 0000 ; Limit Bits 0-15
+ Base0_15 DW 0000 ; Base address Bits 0-15
+ Base16_23 DB 00 ; Base address Bits 16-23
+ AR0_7 R_AR0_7 <> ; Access Rights 0-7
+ LAR16_23 R_LAR16_23 <> ; Limit Bits 16-19 and Access Bits 8-11
+ Base24_31 DB 00 ; Base address Bits 24-31
+SEG_DESCRIPTOR ENDS
+
+;-----------------------------------------------------------------------------
+; Machine Check register definitions
+;
+MCG_CAP EQU 179h
+
+MC0_STATUS EQU 401h
+
+;-----------------------------------------------------------------------------
+; TXT register space definitiions
+;
+TXT_PRIVATE_BASE EQU 0FED20000h
+TXT_PUBLIC_BASE EQU 0FED30000h
+TXT_REGISTER_SPACE_LENGTH EQU 070000h
+
+TXT_STS EQU 0000h
+ TXT_STS_SENTER_DONE_MASK EQU BIT0
+ TXT_STS_SEXIT_DONE_MASK EQU BIT1
+ TXT_STS_MEM_UNLOCK_STS_MASK EQU BIT4
+ TXT_STS_NODMAEN_MASK EQU BIT5
+ TXT_STS_MEMCONFIGLOCK_STS_MASK EQU BIT6
+ TXT_STS_PRIVATEOPEN_STS_MASK EQU BIT7
+ TXT_STS_BLOCKMAP_STS_MASK EQU BIT8
+ TXT_STS_NODMACACHE_STS_MASK EQU BIT9
+ TXT_STS_NODMATABLEPROTECT_STS_MASK EQU BIT10
+ TXT_ESTS EQU 0008h
+ TXT_WAKE_ERROR_STS EQU BIT6
+
+TXT_THREADS_EXIST EQU 0010h
+TXT_THREADS_JOIN EQU 0020h
+TXT_CRASH EQU 0030h
+TXT_CMD_SYS_RESET EQU 0038h
+TXT_CMD_OPEN_PRIVATE EQU 0040h
+TXT_CMD_CLOSE_PRIVATE EQU 0048h
+TXT_POISON EQU 00B0h
+TXT_VER_DID EQU 0110h
+TXT_VER_EID EQU 0118h
+TXT_VER_MIF EQU 0200h
+TXT_CMD_LOCK_MEM_CONFIG EQU 0210h
+TXT_CMD_UNLOCK_MEM_CONFIG EQU 0218h
+TXT_CMD_UNLOCK_MEMORY EQU 0220h
+TXT_CMD_NODMA_EN EQU 0230h
+TXT_CMD_NODMA_DIS EQU 0238h
+TXT_SINIT_BASE EQU 0270h
+TXT_SINIT_SIZE EQU 0278h
+TXT_SINIT_SIZE2 EQU 027Ch
+TXT_SVMM_JOIN EQU 0290h
+TXT_SVMM_JOIN2 EQU 0294h
+TXT_HEAP_BASE EQU 0300h
+TXT_HEAP_SIZE EQU 0308h
+TXT_MSEG_BASE EQU 0310h
+TXT_MSEG_SIZE EQU 0318h
+TXT_SCRATCHPAD EQU 0320h
+TXT_SCRATCHPAD2 EQU 0324h
+TXT_SCRATCHPAD3 EQU 0328h
+TXT_SCRATCHPAD4 EQU 032Ch
+TXT_DPR EQU 0330h
+TXT_CMD_OPEN_LOCALITY1 EQU 0380h
+TXT_CMD_CLOSE_LOCALITY1 EQU 0388h
+TXT_CMD_OPEN_LOCALITY3 EQU 03a0h
+TXT_CMD_CLOSE_LOCALITY3 EQU 03a8h
+TXT_PUBLIC_KEY EQU 0400h
+TXT_TGFX_CMD EQU 0504h
+TXT_TGA_BASE EQU 0510h
+TXT_TGR_BASE EQU 0518h
+TXT_TGTT_BASE EQU 0520h
+TXT_TMSAC EQU 0540h
+ TGTT_128MB EQU BIT0
+ TGTT_256MB EQU BIT1
+ TGTT_512MB EQU BIT1+BIT0
+TXT_VER_FTIF EQU 0800h
+TXT_PCH_DIDVID EQU 0810h
+TXT_CMD_SECRETS EQU 08E0h
+TXT_CMD_NO_SECRETS EQU 08E8h
+TXT_E2STS EQU 08F0h
+ TXT_BLOCK_MEM_STS EQU BIT2
+ TXT_SECRETS_STS EQU BIT1
+ TXT_SLP_ENTRY_ERROR_STS EQU BIT0
+
+MCU_MAX_SIZE EQU 10000h ; 64KB max size per MCU
+MCU_SLOT_SZ_BITS EQU 11 ; 2KB MCU slot size
+MCU_SLOT_SZ EQU 1 SHL MCU_SLOT_SZ_BITS
+
+;-----------------------------------------------------------------------------
+;
+; MCU Constants
+;
+MCU_HEADER_VER EQU 1
+MCU_LOADER_REV EQU 1
+;
+; ProcessorMSR Equates
+;
+PLAT_ID_MSR EQU 17h ; Platform ID
+MCU_LOAD_MSR EQU 79h ; Trigger to load MCU
+MCU_REV_MSR EQU 8Bh ; MCU Revision register
+;
+PLAT_ID_BIT EQU 50 ; Bits 52:50 has the Platform ID
+PLAT_ID_BITMASK EQU 07h ; Bits 52:50 has the Platform ID
+
+EFI_MSR_IA32_THERM_INTERRUPT EQU 019Bh
+;
+; Microcode Update (MCU) Header
+;
+MCU STRUCT
+ headerVer DD ? ; MCU Header Version ( = 00000001h )
+ revision DD ? ; MCU Revision
+ date DD ? ; MCU Date
+ signature DD ? ; MCU Processor Signature
+ checksum DD ? ; MCU Main checksum
+ loaderRev DD ? ; MCU Loader Revision
+ procFlags DD ? ; MCU Processor Flags (Platform ID)
+ dataSize DD ? ; MCU Data Size
+ totalSize DD ? ; MCU Total Size
+ reserved DD 3 dup(?)
+MCU ENDS
+;
+; Extended Signature Table (EST)
+;
+EST STRUCT
+ count DD ? ; EST Count
+ checksum DD ? ; EST Checksum
+ reserved DD 3 dup(?)
+EST ENDS
+;
+; Processor Signature Structure (PSS)
+;
+PSS STRUCT
+ signature DD ? ; PSS Processor Signature
+ procFlags DD ? ; PSS Processor Flags (Platform ID)
+ checksum DD ? ; PSS Checksum
+PSS ENDS
+
+;----------------------------------------------------------------------------
+; APIC definitions
+;
+IA32_APIC_BASE EQU 001Bh ; APIC base MSR
+ BASE_ADDR_MASK EQU 0FFFFF000h
+ EFI_MSR_EXT_XAPIC_LVT_THERM EQU 0833h
+APIC_ID EQU 20h
+ APIC_ID_SHIFT EQU 24
+ICR_LOW EQU 300h
+ICR_HIGH EQU 310h
+SPURIOUS_VECTOR_1 EQU 0F0h
+LOCAL_APIC_THERMAL_DEF EQU 330h
+ B_INTERRUPT_MASK EQU (1 SHL 16)
+ B_DELIVERY_MODE EQU (07h SHL 8)
+ V_MODE_SMI EQU (02h SHL 8)
+ B_VECTOR EQU (0FFh SHL 0)
+
+
+;-----------------------------------------------------------------------------
+; MTRRs
+;
+IA32_MTRR_CAP EQU 0FEh
+IA32_MTRR_PHYSBASE0 EQU 200h
+IA32_MTRR_PHYSMASK0 EQU 201h
+IA32_MTRR_PHYSBASE1 EQU 202h
+IA32_MTRR_PHYSMASK1 EQU 203h
+IA32_MTRR_PHYSBASE2 EQU 204h
+IA32_MTRR_PHYSMASK2 EQU 205h
+IA32_MTRR_PHYSBASE3 EQU 206h
+IA32_MTRR_PHYSMASK3 EQU 207h
+IA32_MTRR_PHYSBASE4 EQU 208h
+IA32_MTRR_PHYSMASK4 EQU 209h
+IA32_MTRR_PHYSBASE5 EQU 20Ah
+IA32_MTRR_PHYSMASK5 EQU 20Bh
+IA32_MTRR_PHYSBASE6 EQU 20Ch
+IA32_MTRR_PHYSMASK6 EQU 20Dh
+IA32_MTRR_PHYSBASE7 EQU 20Eh
+IA32_MTRR_PHYSMASK7 EQU 20Fh
+IA32_MTRR_PHYSBASE8 EQU 210h
+IA32_MTRR_PHYSMASK8 EQU 211h
+IA32_MTRR_PHYSBASE9 EQU 212h
+IA32_MTRR_PHYSMASK9 EQU 213h
+IA32_MTRR_FIX64K_00000 EQU 250h
+IA32_MTRR_FIX16K_80000 EQU 258h
+IA32_MTRR_FIX16K_A0000 EQU 259h
+IA32_MTRR_FIX4K_C0000 EQU 268h
+IA32_MTRR_FIX4K_C8000 EQU 269h
+IA32_MTRR_FIX4K_D0000 EQU 26Ah
+IA32_MTRR_FIX4K_D8000 EQU 26Bh
+IA32_MTRR_FIX4K_E0000 EQU 26Ch
+IA32_MTRR_FIX4K_E8000 EQU 26Dh
+IA32_MTRR_FIX4K_F0000 EQU 26Eh
+IA32_MTRR_FIX4K_F8000 EQU 26Fh
+IA32_CR_PAT EQU 277h
+IA32_MTRR_DEF_TYPE EQU 2FFh
+NO_EVICT_MODE EQU 2E0h
+
+;
+; Only low order bits are assumed
+;
+MTRR_MASK EQU 0FFFFF000h
+
+MTRR_ENABLE EQU (1 SHL 11)
+MTRR_FIXED_ENABLE EQU (1 SHL 10)
+MTRR_VALID EQU (1 SHL 11)
+UC EQU 00h
+WB EQU 06h
+
+MTRR_VCNT EQU 8
+
+;-----------------------------------------------------------------------------
+;
+; CPU generic definition
+;
+IA32_CPUID_SMX_B EQU 6
+
+;-----------------------------------------------------------------------------
+;
+; AP communication area
+;
+
+MCU_BASE_ADDR EQU TXT_SINIT_SIZE
+BIOACM_ADDR EQU TXT_SINIT_SIZE2
+APINIT_ADDR EQU TXT_SVMM_JOIN
+SEMAPHORE EQU TXT_SVMM_JOIN2
+
+IA32_MISC_ENABLE_MSR EQU 1A0h
+IA32_EFER_MSR EQU 0C0000080h
+LME EQU BIT8
+
+IFNDEF MKF_TXT_RLP_INIT
+MKF_TXT_RLP_INIT EQU 01h
+ENDIF
diff --git a/ReferenceCode/Haswell/Library/BootGuardLib.cif b/ReferenceCode/Haswell/Library/BootGuardLib.cif
new file mode 100644
index 0000000..2f3587a
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/BootGuardLib.cif
@@ -0,0 +1,11 @@
+<component>
+ name = "BootGuardLib"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\Library\"
+ RefName = "BootGuardLib"
+[files]
+"BootGuardLib.sdl"
+"BootGuardLib.mak"
+"BootGuardLib\BootGuardLib.inf"
+"BootGuardLib\BootGuardLibrary.c"
+<endComponent>
diff --git a/ReferenceCode/Haswell/Library/BootGuardLib.mak b/ReferenceCode/Haswell/Library/BootGuardLib.mak
new file mode 100644
index 0000000..5fa59bc
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/BootGuardLib.mak
@@ -0,0 +1,20 @@
+# MAK file for the ModulePart:CpuPlatformLib
+
+$(BootGuardLib_LIB) : BootGuardLib
+
+BootGuardLib : $(BUILD_DIR)\BootGuardLib.mak BootGuardLibBin
+
+$(BUILD_DIR)\BootGuardLib.mak : $(BootGuardLib_DIR)\$(@B).cif $(BootGuardLib_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(BootGuardLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+BootGuardLibBin :
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ BUILD_DIR=$(BUILD_DIR) \
+ /f $(BUILD_DIR)\BootGuardLib.mak all\
+ "MY_INCLUDES=$(EDK_INCLUDES) $(EdkIIGlueLib_INCLUDES) $(PROJECT_CPU_INCLUDES) $(INTEL_PCH_INCLUDES)" \
+ TYPE=LIBRARY "PARAMETERS=LIBRARY_NAME=$$(BootGuardLib_LIB)"
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ BUILD_DIR=$(BUILD_DIR)\IA32 \
+ /f $(BUILD_DIR)\BootGuardLib.mak all\
+ "MY_INCLUDES=$(EDK_INCLUDES) $(EdkIIGlueLib_INCLUDES) $(PROJECT_CPU_INCLUDES) $(INTEL_PCH_INCLUDES)" \
+ TYPE=PEI_LIBRARY "PARAMETERS=LIBRARY_NAME=$$(BootGuardLib_LIB)"
diff --git a/ReferenceCode/Haswell/Library/BootGuardLib.sdl b/ReferenceCode/Haswell/Library/BootGuardLib.sdl
new file mode 100644
index 0000000..8356d53
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/BootGuardLib.sdl
@@ -0,0 +1,32 @@
+TOKEN
+ Name = BootGuardLib_SUPPORT
+ Value = "1"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+ Help = "Main switch to enable BootGuardLib support in Project"
+End
+
+TOKEN
+ Name = "BootGuardLib_LIB"
+ Value = "$$(LIB_BUILD_DIR)\BootGuardLib.lib"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+PATH
+ Name = "BootGuardLib_DIR"
+End
+
+ELINK
+ Name = "/I$(BootGuardLib_DIR)\BootGuardLib"
+ Parent = "PROJECT_CPU_INCLUDES"
+ InvokeOrder = AfterParent
+End
+
+MODULE
+ Help = "Includes BootGuardLib.mak to Project"
+ File = "BootGuardLib.mak"
+End
+
diff --git a/ReferenceCode/Haswell/Library/BootGuardLib/BootGuardLib.inf b/ReferenceCode/Haswell/Library/BootGuardLib/BootGuardLib.inf
new file mode 100644
index 0000000..5af1ded
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/BootGuardLib/BootGuardLib.inf
@@ -0,0 +1,64 @@
+## @file
+# Component description file for Boot Guard Library
+#
+#@copyright
+# Copyright (c) 2012 - 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 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
+#
+
+[defines]
+BASE_NAME = BootGuardLib
+COMPONENT_TYPE = LIBRARY
+
+[sources.common]
+ BootGuardLibrary.c
+
+[sources.ia32]
+
+[sources.x64]
+
+[sources.ipf]
+
+[includes.common]
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include/Library
+
+#
+# EDK II Glue Library utilizes some standard headers from EDK
+#
+ $(EFI_SOURCE)
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+
+[libraries.common]
+ EdkIIGlueBasePciLibPciExpress
+ CpuPlatformLib
+
+[nmake.common]
diff --git a/ReferenceCode/Haswell/Library/BootGuardLib/BootGuardLibrary.c b/ReferenceCode/Haswell/Library/BootGuardLib/BootGuardLibrary.c
new file mode 100644
index 0000000..e35d42f
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/BootGuardLib/BootGuardLibrary.c
@@ -0,0 +1,121 @@
+/** @file
+ BootGuardLibrary implementation.
+
+@copyright
+ Copyright (c) 2012 - 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 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
+**/
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueBase.h"
+#include "EdkIIGluePeim.h"
+#include "CpuAccess.h"
+#include "CpuPlatformLib.h"
+#endif
+
+/**
+ Determine if Boot Guard is supported
+
+ @retval TRUE - Processor is Boot Guard capable.
+ @retval FALSE - Processor is not Boot Guard capable.
+
+**/
+BOOLEAN
+IsBootGuardSupported (
+ VOID
+ )
+{
+ UINT64 BootGuardBootStatus;
+ UINT32 BootGuardAcmStatus;
+ UINT64 BootGuardCapability;
+ CPU_STEPPING CpuSteppingId;
+
+ //
+ // Return unsupported if processor is not ULT sku
+ //
+ if(GetCpuSku() != EnumCpuUlt) {
+ return FALSE;
+ }
+
+ BootGuardBootStatus = *(UINT64 *) (UINTN) (TXT_PUBLIC_BASE + R_CPU_BOOT_GUARD_BOOTSTATUS);
+ BootGuardAcmStatus = *(UINT32 *) (UINTN) (TXT_PUBLIC_BASE + R_CPU_BOOT_GUARD_ACM_STATUS);
+ BootGuardCapability = AsmReadMsr64 (MSR_BOOT_GUARD_SACM_INFO) & BIT32;
+ CpuSteppingId = GetCpuStepping();
+
+ if (CpuSteppingId >= EnumHswUltC0) {
+ if (BootGuardCapability != 0) {
+ DEBUG ((EFI_D_ERROR, "Processor supports Boot Guard.\n"));
+ return TRUE;
+ } else {
+ DEBUG ((EFI_D_ERROR, "Processor does not support Boot Guard.\n"));
+ return FALSE;
+ }
+ } else {
+ if(((BootGuardBootStatus & BIT62) == 0) && // Check for ACM not found in FIT
+ ((BootGuardAcmStatus & B_BOOT_GUARD_ACM_ERRORCODE_MASK) == 0) && // Check for ACM failed to load/run successfully
+ ((BootGuardAcmStatus & BIT31) == 0)) { // Check if ACM Entered
+ DEBUG ((EFI_D_ERROR, "Processor does not support Boot Guard.\n"));
+ return FALSE;
+ } else {
+ DEBUG ((EFI_D_ERROR, "Processor supports Boot Guard.\n"));
+ return TRUE;
+ }
+ }
+}
+
+/**
+ Stop PBE timer if system is in Boot Guard boot
+
+ @retval EFI_SUCCESS - Stop PBE timer
+ @retval EFI_UNSUPPORTED - Not in Boot Guard boot mode.
+**/
+EFI_STATUS
+StopPbeTimer (
+ VOID
+ )
+{
+ UINT64 BootGuardBootStatus;
+ UINT64 BootGuardOperationMode;
+
+ if (IsBootGuardSupported()) {
+ BootGuardBootStatus = (*(UINT64 *) (UINTN) (TXT_PUBLIC_BASE + R_CPU_BOOT_GUARD_BOOTSTATUS) & (BIT63|BIT62));
+ BootGuardOperationMode = AsmReadMsr64 (MSR_BOOT_GUARD_SACM_INFO);
+
+ //
+ // Stop PBET if Verified/Measured/NEM bit is set in MSR 0x13A or
+ // Boot Guard fails to launch or fails to execute successfully for avoiding brick platform
+ //
+
+ if (BootGuardBootStatus == V_CPU_BOOT_GUARD_LOAD_ACM_SUCCESS) {
+ if (BootGuardOperationMode == 0) {
+ DEBUG ((EFI_D_ERROR, "Platform in Legacy boot mode.\n"));
+ return EFI_UNSUPPORTED;
+ } else {
+ DEBUG ((EFI_D_ERROR, "Platform in Boot Guard Boot mode.\n"));
+ }
+ } else {
+ DEBUG ((EFI_D_ERROR, "Boot Guard ACM launch failed or ACM execution failed.\n"));
+ }
+
+ DEBUG ((EFI_D_ERROR, "Disable PBET\n"));
+ AsmWriteMsr64 (MSR_BC_PBEC, B_STOP_PBET);
+ } else {
+ DEBUG ((EFI_D_ERROR, "Boot Guard is not supported.\n"));
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git a/ReferenceCode/Haswell/Library/CpuPlatformLib.cif b/ReferenceCode/Haswell/Library/CpuPlatformLib.cif
new file mode 100644
index 0000000..7f1e13c
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/CpuPlatformLib.cif
@@ -0,0 +1,12 @@
+<component>
+ name = "CpuPlatformLib"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\Library\"
+ RefName = "CpuPlatformLib"
+[files]
+"CpuPlatformLib.sdl"
+"CpuPlatformLib.mak"
+"CpuPlatformLib\CpuPlatformLib.inf"
+"CpuPlatformLib\CpuPlatformLibrary.c"
+"CpuPlatformLib\CpuPlatformLibrary.h"
+<endComponent>
diff --git a/ReferenceCode/Haswell/Library/CpuPlatformLib.mak b/ReferenceCode/Haswell/Library/CpuPlatformLib.mak
new file mode 100644
index 0000000..a9151b4
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/CpuPlatformLib.mak
@@ -0,0 +1,28 @@
+# MAK file for the ModulePart:CpuPlatformLib
+
+$(CpuPlatformLib_LIB) : CpuPlatformLib
+
+CpuPlatformLib : $(BUILD_DIR)\CpuPlatformLib.mak CpuPlatformLibBin
+
+$(BUILD_DIR)\CpuPlatformLib.mak : $(CpuPlatformLib_DIR)\$(@B).cif $(CpuPlatformLib_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(CpuPlatformLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+CpuPlatformLib_MY_INCLUDES=\
+ $(EDK_INCLUDES)\
+ $(EdkIIGlueLib_INCLUDES)\
+ $(PROJECT_CPU_INCLUDES)\
+ /I$(PROJECT_CPU_ROOT)\Library\CpuPlatformLib\
+ /I$(INTEL_PCH_DIR)\Include\
+ /I$(INTEL_PCH_DIR)\Include\Library
+
+CpuPlatformLibBin :
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ BUILD_DIR=$(BUILD_DIR) \
+ /f $(BUILD_DIR)\CpuPlatformLib.mak all\
+ "MY_INCLUDES=$(CpuPlatformLib_MY_INCLUDES)" \
+ TYPE=LIBRARY "PARAMETERS=LIBRARY_NAME=$$(CpuPlatformLib_LIB)"
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ BUILD_DIR=$(BUILD_DIR)\IA32 \
+ /f $(BUILD_DIR)\CpuPlatformLib.mak all\
+ "MY_INCLUDES=$(CpuPlatformLib_MY_INCLUDES)" \
+ TYPE=PEI_LIBRARY "PARAMETERS=LIBRARY_NAME=$$(CpuPlatformLib_LIB)"
diff --git a/ReferenceCode/Haswell/Library/CpuPlatformLib.sdl b/ReferenceCode/Haswell/Library/CpuPlatformLib.sdl
new file mode 100644
index 0000000..eb60154
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/CpuPlatformLib.sdl
@@ -0,0 +1,31 @@
+TOKEN
+ Name = CpuPlatformLib_SUPPORT
+ Value = "1"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+ Help = "Main switch to enable ThunkLib support in Project"
+End
+
+TOKEN
+ Name = "CpuPlatformLib_LIB"
+ Value = "$$(LIB_BUILD_DIR)\CpuPlatformLib.lib"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+PATH
+ Name = "CpuPlatformLib_DIR"
+End
+
+MODULE
+ Help = "Includes ThunkLib.mak to Project"
+ File = "CpuPlatformLib.mak"
+End
+
+ELINK
+ Name = "/I$(CpuPlatformLib_DIR)\CpuPlatformLib"
+ Parent = "PROJECT_CPU_INCLUDES"
+ InvokeOrder = AfterParent
+End
diff --git a/ReferenceCode/Haswell/Library/CpuPlatformLib/CpuPlatformLib.inf b/ReferenceCode/Haswell/Library/CpuPlatformLib/CpuPlatformLib.inf
new file mode 100644
index 0000000..9a0e283
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/CpuPlatformLib/CpuPlatformLib.inf
@@ -0,0 +1,66 @@
+## @file
+# Component description file for CPU Platform Lib
+#
+#@copyright
+# Copyright (c) 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
+#
+
+[defines]
+BASE_NAME = CpuPlatformLib
+COMPONENT_TYPE = LIBRARY
+
+[sources.common]
+ CpuPlatformLibrary.h
+ CpuPlatformLibrary.c
+
+[sources.ia32]
+
+[sources.x64]
+
+[sources.ipf]
+
+[includes.common]
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include/Library
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library
+
+#
+# EDK II Glue Library utilizes some standard headers from EDK
+#
+ $(EFI_SOURCE)
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+
+[libraries.common]
+ PchPlatformLib
+ EdkIIGlueBasePciLibPciExpress
+
+[nmake.common]
diff --git a/ReferenceCode/Haswell/Library/CpuPlatformLib/CpuPlatformLibrary.c b/ReferenceCode/Haswell/Library/CpuPlatformLib/CpuPlatformLibrary.c
new file mode 100644
index 0000000..043bfae
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/CpuPlatformLib/CpuPlatformLibrary.c
@@ -0,0 +1,476 @@
+/** @file
+ CPU Platform Lib implementation.
+
+@copyright
+ Copyright (c) 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
+
+**/
+#include "CpuPlatformLibrary.h"
+
+/**
+ Return CPU Family ID
+
+ @retval CPU_FAMILY CPU Family ID
+**/
+CPU_FAMILY
+EFIAPI
+GetCpuFamily (
+ VOID
+ )
+{
+ EFI_CPUID_REGISTER Cpuid;
+ ///
+ /// Read the CPUID information
+ ///
+ AsmCpuid (CPUID_VERSION_INFO, &Cpuid.RegEax, &Cpuid.RegEbx, &Cpuid.RegEcx, &Cpuid.RegEdx);
+ return ((CPU_FAMILY) (Cpuid.RegEax & CPUID_FULL_FAMILY_MODEL));
+}
+
+/**
+ Return Cpu stepping type
+
+ @retval UINT8 Cpu stepping type
+**/
+CPU_STEPPING
+EFIAPI
+GetCpuStepping (
+ VOID
+ )
+{
+ EFI_CPUID_REGISTER Cpuid;
+ ///
+ /// Read the CPUID information
+ ///
+ AsmCpuid (CPUID_VERSION_INFO, &Cpuid.RegEax, &Cpuid.RegEbx, &Cpuid.RegEcx, &Cpuid.RegEdx);
+ return ((CPU_STEPPING) (Cpuid.RegEax & CPUID_FULL_STEPPING));
+}
+
+/**
+ Determine if CPU is supported
+
+ @retval TRUE CPU is supported
+ @retval FALSE CPU is not supported
+**/
+BOOLEAN
+IsCpuSupported (
+ VOID
+ )
+{
+ if (GetCpuFamily() == EnumCpuMax) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ Return CPU Sku
+
+ @retval UINT8 CPU Sku
+**/
+UINT8
+EFIAPI
+GetCpuSku (
+ VOID
+ )
+{
+ UINT8 CpuType;
+ EFI_CPUID_REGISTER Cpuid;
+ ///
+ /// Read the CPUID information
+ ///
+ AsmCpuid (CPUID_VERSION_INFO, &Cpuid.RegEax, &Cpuid.RegEbx, &Cpuid.RegEcx, &Cpuid.RegEdx);
+ switch (Cpuid.RegEax & CPUID_FULL_FAMILY_MODEL) {
+ case CPUID_FULL_FAMILY_MODEL_HASWELL_ULT:
+ CpuType = EnumCpuUlt;
+ break;
+
+ case CPUID_FULL_FAMILY_MODEL_HASWELL:
+ case CPUID_FULL_FAMILY_MODEL_CRYSTALWELL:
+ CpuType = EnumCpuTrad;
+ break;
+
+ default:
+ CpuType = EnumCpuUnknown;
+ DEBUG ((EFI_D_ERROR, "Unsupported CPU SKU, CpuFamilyId: 0x%08X!\n", (Cpuid.RegEax & CPUID_FULL_FAMILY_MODEL)));
+ ASSERT (FALSE);
+ break;
+ }
+
+ return CpuType;
+}
+
+EFI_STATUS
+EFIAPI
+MailboxWrite (
+ IN UINT32 MailboxType,
+ IN UINT32 MailboxCommand,
+ IN UINT32 MailboxData,
+ OUT UINT32 *MailboxStatus
+ )
+/**
+ Generic Mailbox function for mailbox write commands. This function will
+ poll the mailbox interface for control, issue the write request, poll
+ for completion, and verify the write was succussful.
+
+ @param[IN] MailboxType,
+ @param[IN] MailboxCommand,
+ @param[IN] MailboxData,
+ @param[OUT] *MailboxStatus
+
+ @retval EFI_STATUS
+**/
+{
+ EFI_STATUS Status;
+ UINT64 MsrData;
+ UINT32 MchBar;
+ OC_MAILBOX_FULL OcMailboxFull;
+ OC_MAILBOX_FULL OcMailboxFullVerify;
+ PCODE_MAILBOX_FULL PcodeMailboxFull;
+ PCODE_MAILBOX_FULL PcodeMailboxFullVerify;
+
+ ///
+ /// Poll the run/busy to ensure the interface is available
+ ///
+ Status = PollMailboxReady(MailboxType);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ DEBUG ((EFI_D_INFO, "(MAILBOX) Mailbox Write Command = %2X\n", (UINT8)MailboxCommand));
+
+ switch (MailboxType)
+ {
+ case MAILBOX_TYPE_PCODE:
+ ///
+ /// Copy in Mailbox data and write the PCODE mailbox DATA field
+ ///
+ PcodeMailboxFull.Interface.InterfaceData = MailboxCommand;
+ PcodeMailboxFull.Data = MailboxData;
+ MchBar = (MmioRead32 (MmPciAddress (0, 0, 0, 0, MCHBAR_OFFSET)) &~BIT0);
+
+ MmioWrite32 ( (MchBar + PCODE_MAILBOX_DATA_OFFSET), PcodeMailboxFull.Data);
+
+ ///
+ /// Set the Run/Busy bit to signal mailbox data is ready to process
+ ///
+ PcodeMailboxFull.Interface.Fields.RunBusy = 1;
+ MmioWrite32 ( (MchBar + PCODE_MAILBOX_INTERFACE_OFFSET), PcodeMailboxFull.Interface.InterfaceData);
+
+ ///
+ /// Poll run/busy to indicate the completion of write request
+ ///
+ PollMailboxReady(MailboxType);
+
+ ///
+ /// Read the BIOS PCODE mailbox to verify write completion success.
+ /// Mailbox protocol requires software to read back the interface twice
+ /// to ensure the read results are consistent.
+ ///
+ PcodeMailboxFull.Interface.InterfaceData = MmioRead32 (MchBar + PCODE_MAILBOX_INTERFACE_OFFSET);
+ PcodeMailboxFull.Data = MmioRead32 (MchBar + PCODE_MAILBOX_DATA_OFFSET);
+
+ PchPmTimerStall(MAILBOX_READ_TIMEOUT);
+
+ ///
+ /// Read twice to verify data is consitent
+ ///
+ PcodeMailboxFullVerify.Interface.InterfaceData = MmioRead32 (MchBar + PCODE_MAILBOX_INTERFACE_OFFSET);
+ PcodeMailboxFullVerify.Data = MmioRead32 (MchBar + PCODE_MAILBOX_DATA_OFFSET);
+
+ ///
+ /// If the data is inconsistent, we cannot trust the results
+ ///
+ if (PcodeMailboxFull.Interface.InterfaceData != PcodeMailboxFullVerify.Interface.InterfaceData) {
+ if (PcodeMailboxFull.Data != PcodeMailboxFullVerify.Data) {
+ DEBUG ((EFI_D_ERROR, "(MAILBOX) Mailbox read data is corrupted.\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ ///
+ /// Copy PCODE mailbox completion code
+ ///
+ *MailboxStatus = (UINT32) PcodeMailboxFull.Interface.Fields.Command;
+ break;
+
+ case MAILBOX_TYPE_OC:
+ ///
+ /// Set the Run/Busy bit to signal mailbox data is ready to process
+ ///
+ OcMailboxFull.Interface.InterfaceData = MailboxCommand;
+ OcMailboxFull.Data = MailboxData;
+ OcMailboxFull.Interface.Fields.RunBusy = 1;
+ CopyMem (&MsrData, &OcMailboxFull, sizeof(MsrData));
+
+ ///
+ /// Write mailbox command to OC mailbox
+ ///
+ AsmWriteMsr64 (OC_MAILBOX_MSR, MsrData);
+
+ ///
+ /// Poll run/busy to indicate the completion of write request
+ ///
+ PollMailboxReady(MailboxType);
+
+ ///
+ /// Read the mailbox command from OC mailbox. Read twice to ensure data.
+ ///
+ MsrData = AsmReadMsr64 (OC_MAILBOX_MSR);
+ CopyMem (&OcMailboxFull, &MsrData, sizeof(OcMailboxFull));
+
+ PchPmTimerStall(MAILBOX_READ_TIMEOUT);
+
+ MsrData = AsmReadMsr64 (OC_MAILBOX_MSR);
+ CopyMem (&OcMailboxFullVerify, &MsrData, sizeof(OcMailboxFullVerify));
+
+ ///
+ /// If the data is inconsistent, we cannot trust the results
+ ///
+ if (OcMailboxFull.Interface.InterfaceData != OcMailboxFullVerify.Interface.InterfaceData) {
+ if (OcMailboxFull.Data != OcMailboxFullVerify.Data) {
+ DEBUG ((EFI_D_ERROR, "(MAILBOX) Mailbox read data is corrupted.\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ ///
+ /// Copy Overclocking mailbox completion code and read results
+ ///
+ *MailboxStatus = OcMailboxFull.Interface.Fields.CommandCompletion;
+ break;
+
+ default:
+ DEBUG ((EFI_D_ERROR, "(MAILBOX) Unrecognized Mailbox Type.\n"));
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+
+ DEBUG ((EFI_D_INFO, "(MAILBOX) Mailbox Status = %2X\n", *MailboxStatus));
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+MailboxRead (
+ IN UINT32 MailboxType,
+ IN UINT32 MailboxCommand,
+ OUT UINT32 *MailboxDataPtr,
+ OUT UINT32 *MailboxStatus
+ )
+/**
+ Generic Mailbox function for mailbox read commands. This function will write
+ the read request, and populate the read results in the output data.
+
+ @param[IN] MailboxType,
+ @param[IN] MailboxCommand,
+ @param[OUT] *MailboxDataPtr,
+ @param[OUT] *MailboxStatus
+
+ @retval EFI_STATUS
+**/
+{
+ EFI_STATUS Status;
+ UINT64 MsrData;
+ UINT32 MchBar;
+ PCODE_MAILBOX_FULL PcodeMailboxFull;
+ PCODE_MAILBOX_FULL PcodeMailboxFullVerify;
+ OC_MAILBOX_FULL OcMailboxFull;
+ OC_MAILBOX_FULL OcMailboxFullVerify;
+
+ ///
+ /// Poll the run/busy to ensure the interface is available
+ ///
+ Status = PollMailboxReady(MailboxType);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ DEBUG ((EFI_D_INFO, "(MAILBOX) Mailbox Read Command = %2X\n", (UINT8)MailboxCommand));
+
+ switch (MailboxType)
+ {
+ case MAILBOX_TYPE_PCODE:
+ ///
+ /// Write the PCODE mailbox read request.
+ /// Read requests only require a write to the PCODE interface mailbox.
+ /// The read results will be updated in the data mailbox.
+ ///
+ PcodeMailboxFull.Interface.InterfaceData = MailboxCommand;
+ PcodeMailboxFull.Interface.Fields.RunBusy = 1;
+ MchBar = (MmioRead32 (MmPciAddress (0, 0, 0, 0, MCHBAR_OFFSET)) &~BIT0);
+
+ MmioWrite32 ( (MchBar + PCODE_MAILBOX_INTERFACE_OFFSET), PcodeMailboxFull.Interface.InterfaceData);
+
+ ///
+ /// Poll run/busy to indicate the completion of read request
+ ///
+ PollMailboxReady(MailboxType);
+
+ ///
+ /// Read the BIOS PCODE mailbox to verify read completion success.
+ /// Mailbox protocol requires software to read back the interface twice
+ /// to ensure the read results are consistent.
+ ///
+ PcodeMailboxFull.Interface.InterfaceData = MmioRead32 (MchBar + PCODE_MAILBOX_INTERFACE_OFFSET);
+ PcodeMailboxFull.Data = MmioRead32 (MchBar + PCODE_MAILBOX_DATA_OFFSET);
+
+ PchPmTimerStall(MAILBOX_READ_TIMEOUT);
+
+ ///
+ /// Read twice to verify data is consitent
+ ///
+ PcodeMailboxFullVerify.Interface.InterfaceData = MmioRead32 (MchBar + PCODE_MAILBOX_INTERFACE_OFFSET);
+ PcodeMailboxFullVerify.Data = MmioRead32 (MchBar + PCODE_MAILBOX_DATA_OFFSET);
+
+ ///
+ /// If the data is inconsistent, we cannot trust the results
+ ///
+ if (PcodeMailboxFull.Interface.InterfaceData != PcodeMailboxFullVerify.Interface.InterfaceData) {
+ if (PcodeMailboxFull.Data != PcodeMailboxFullVerify.Data) {
+ DEBUG ((EFI_D_ERROR, "(MAILBOX) Mailbox read data is corrupted.\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ ///
+ /// Copy PCODE mailbox completion code and read results
+ ///
+ *MailboxStatus = (UINT32) PcodeMailboxFull.Interface.InterfaceData;
+ CopyMem(MailboxDataPtr, &PcodeMailboxFull.Data, sizeof(UINT32));
+ break;
+
+ case MAILBOX_TYPE_OC:
+ ///
+ /// Set the Run/Busy bit to signal mailbox data is ready to process
+ ///
+ OcMailboxFull.Interface.InterfaceData = MailboxCommand;
+ OcMailboxFull.Data = *MailboxDataPtr;
+ OcMailboxFull.Interface.Fields.RunBusy = 1;
+ CopyMem (&MsrData, &OcMailboxFull, sizeof(MsrData));
+
+ ///
+ /// Write mailbox command to OC mailbox
+ ///
+ AsmWriteMsr64 (OC_MAILBOX_MSR, MsrData);
+
+ ///
+ /// Poll run/busy to indicate the completion of write request
+ ///
+ PollMailboxReady(MailboxType);
+
+ ///
+ /// Read the OC mailbox to verify read completion success.
+ /// Mailbox protocol requires software to read back the interface twice
+ /// to ensure the read results are consistent.
+ ///
+ MsrData = AsmReadMsr64 (OC_MAILBOX_MSR);
+ CopyMem (&OcMailboxFull, &MsrData, sizeof(OcMailboxFull));
+
+ PchPmTimerStall(MAILBOX_READ_TIMEOUT);
+
+ MsrData = AsmReadMsr64 (OC_MAILBOX_MSR);
+ CopyMem (&OcMailboxFullVerify, &MsrData, sizeof(OcMailboxFullVerify));
+
+ ///
+ /// If the data is inconsistent, we cannot trust the results
+ ///
+ if (OcMailboxFull.Interface.InterfaceData != OcMailboxFullVerify.Interface.InterfaceData) {
+ if (OcMailboxFull.Data != OcMailboxFullVerify.Data) {
+ DEBUG ((EFI_D_ERROR, "(MAILBOX) Mailbox read data is corrupted.\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ ///
+ /// Copy Overclocking mailbox completion code and read results
+ ///
+ *MailboxStatus = OcMailboxFull.Interface.Fields.CommandCompletion;
+ CopyMem(MailboxDataPtr, &OcMailboxFull.Data, sizeof(UINT32));
+ break;
+
+ default:
+ DEBUG ((EFI_D_ERROR, "(MAILBOX) Unrecognized Mailbox Type.\n"));
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+
+ DEBUG ((EFI_D_INFO, "(MAILBOX) Mailbox Status = %2X\n", *MailboxStatus));
+
+ return Status;
+}
+
+/**
+ Poll the run/busy bit of the mailbox until available or timeout expires.
+
+ @param[IN] MailboxType,
+
+ @retval EFI_STATUS
+**/
+EFI_STATUS
+EFIAPI
+PollMailboxReady (
+ IN UINT32 MailboxType
+ )
+{
+ EFI_STATUS Status;
+ UINT16 StallCount;
+ UINT8 RunBusyBit;
+ UINT64 MsrData;
+ UINT32 MchBar;
+ OC_MAILBOX_FULL OcMailboxFull;
+ PCODE_MAILBOX_INTERFACE PcodeMailboxInterface;
+
+ Status = EFI_SUCCESS;
+ StallCount = 0;
+ RunBusyBit = 1;
+
+ do {
+ switch (MailboxType)
+ {
+ case MAILBOX_TYPE_PCODE:
+ ///
+ /// Read the MMIO run/busy state
+ ///
+ MchBar = (MmioRead32 (MmPciAddress (0, 0, 0, 0, MCHBAR_OFFSET)) &~BIT0);
+ PcodeMailboxInterface.InterfaceData = MmioRead32 (MchBar + PCODE_MAILBOX_INTERFACE_OFFSET);
+ RunBusyBit = (UINT8) PcodeMailboxInterface.Fields.RunBusy;
+ break;
+
+ case MAILBOX_TYPE_OC:
+ ///
+ /// Read the OC mailbox run/busy state
+ ///
+ MsrData = AsmReadMsr64(OC_MAILBOX_MSR);
+ CopyMem(&OcMailboxFull.Data, &MsrData, sizeof(OcMailboxFull));
+ RunBusyBit = OcMailboxFull.Interface.Fields.RunBusy;
+ break;
+ }
+ //
+ // Wait for 1us
+ //
+ PchPmTimerStall(MAILBOX_WAIT_STALL);
+ StallCount++;
+ }
+ while ((RunBusyBit == 1) && (StallCount < MAILBOX_WAIT_TIMEOUT));
+
+ if ((RunBusyBit == 1) && (StallCount == MAILBOX_WAIT_TIMEOUT)) {
+ DEBUG ((EFI_D_ERROR, "(MAILBOX) Mailbox interface timed out.\n"));
+ Status = EFI_TIMEOUT;
+ }
+ return Status;
+}
+
diff --git a/ReferenceCode/Haswell/Library/CpuPlatformLib/CpuPlatformLibrary.h b/ReferenceCode/Haswell/Library/CpuPlatformLib/CpuPlatformLibrary.h
new file mode 100644
index 0000000..4d5d720
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/CpuPlatformLib/CpuPlatformLibrary.h
@@ -0,0 +1,31 @@
+/** @file
+ Header file for Cpu Platform Lib implementation.
+
+@copyright
+ Copyright (c) 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
+**/
+#ifndef _CPU_PLATFORM_LIBRARY_IMPLEMENTATION_H_
+#define _CPU_PLATFORM_LIBRARY_IMPLEMENTATION_H_
+
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueBase.h"
+#include "EdkIIGluePeim.h"
+#include "CpuAccess.h"
+#include "CpuPlatformLib.h"
+#include "PchAccess.h"
+#include "PchPlatformLib.h"
+#endif
+
+#endif
diff --git a/ReferenceCode/Haswell/Library/OcPlatformLib.cif b/ReferenceCode/Haswell/Library/OcPlatformLib.cif
new file mode 100644
index 0000000..7699c9a
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/OcPlatformLib.cif
@@ -0,0 +1,12 @@
+<component>
+ name = "OcPlatformLib"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\Library\"
+ RefName = "OcPlatformLib"
+[files]
+"OcPlatformLib.sdl"
+"OcPlatformLib.mak"
+"OverclockingLib\OverclockingLib.inf"
+"OverclockingLib\OverclockingLibrary.c"
+"OverclockingLib\OverclockingLibrary.h"
+<endComponent>
diff --git a/ReferenceCode/Haswell/Library/OcPlatformLib.mak b/ReferenceCode/Haswell/Library/OcPlatformLib.mak
new file mode 100644
index 0000000..512f086
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/OcPlatformLib.mak
@@ -0,0 +1,20 @@
+# MAK file for the ModulePart:CpuPlatformLib
+
+$(OcPlatformLib_LIB) : OcPlatformLib
+
+OcPlatformLib : $(BUILD_DIR)\OcPlatformLib.mak OcPlatformLibBin
+
+$(BUILD_DIR)\OcPlatformLib.mak : $(OcPlatformLib_DIR)\$(@B).cif $(OcPlatformLib_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(OcPlatformLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+OcPlatformLibBin :
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ BUILD_DIR=$(BUILD_DIR) \
+ /f $(BUILD_DIR)\OcPlatformLib.mak all\
+ "MY_INCLUDES=$(EDK_INCLUDES) $(EdkIIGlueLib_INCLUDES) $(PROJECT_CPU_INCLUDES) $(INTEL_PCH_INCLUDES)" \
+ TYPE=LIBRARY "PARAMETERS=LIBRARY_NAME=$$(OcPlatformLib_LIB)"
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ BUILD_DIR=$(BUILD_DIR)\IA32 \
+ /f $(BUILD_DIR)\OcPlatformLib.mak all\
+ "MY_INCLUDES=$(EDK_INCLUDES) $(EdkIIGlueLib_INCLUDES) $(PROJECT_CPU_INCLUDES) $(INTEL_PCH_INCLUDES)" \
+ TYPE=PEI_LIBRARY "PARAMETERS=LIBRARY_NAME=$$(OcPlatformLib_LIB)"
diff --git a/ReferenceCode/Haswell/Library/OcPlatformLib.sdl b/ReferenceCode/Haswell/Library/OcPlatformLib.sdl
new file mode 100644
index 0000000..bd92181
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/OcPlatformLib.sdl
@@ -0,0 +1,32 @@
+TOKEN
+ Name = OcPlatformLib_SUPPORT
+ Value = "1"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+ Help = "Main switch to enable OcLib support in Project"
+End
+
+TOKEN
+ Name = "OcPlatformLib_LIB"
+ Value = "$$(LIB_BUILD_DIR)\OcPlatformLib.lib"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+PATH
+ Name = "OcPlatformLib_DIR"
+End
+
+ELINK
+ Name = "/I$(OcPlatformLib_DIR)\OverclockingLib"
+ Parent = "PROJECT_CPU_INCLUDES"
+ InvokeOrder = AfterParent
+End
+
+MODULE
+ Help = "Includes OcPlatformLib.mak to Project"
+ File = "OcPlatformLib.mak"
+End
+
diff --git a/ReferenceCode/Haswell/Library/OverclockingLib/OverclockingLib.inf b/ReferenceCode/Haswell/Library/OverclockingLib/OverclockingLib.inf
new file mode 100644
index 0000000..8c286ef
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/OverclockingLib/OverclockingLib.inf
@@ -0,0 +1,69 @@
+## @file
+# Component description file for CPU PPI library.
+#
+#@copyright
+# Copyright (c) 2005 - 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
+#
+
+[defines]
+BASE_NAME = OverclockingLib
+COMPONENT_TYPE = LIBRARY
+
+[sources.common]
+ OverclockingLibrary.c
+ OverclockingLibrary.h
+
+[includes.common]
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Pei/Include
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include/Library
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Library
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Library/CpuPlatformLib
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library
+
+#
+# Edk II Glue Library, some hearder are included by R9 header so have to include
+#
+ $(EFI_SOURCE)
+ $(EFI_SOURCE)/Framework
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+
+[libraries.common]
+ CpuPlatformLib
+
+[nmake.common]
+C_STD_INCLUDE=
+
+
diff --git a/ReferenceCode/Haswell/Library/OverclockingLib/OverclockingLibrary.c b/ReferenceCode/Haswell/Library/OverclockingLib/OverclockingLibrary.c
new file mode 100644
index 0000000..e4576fc
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/OverclockingLib/OverclockingLibrary.c
@@ -0,0 +1,621 @@
+/** @file
+ CPU Platform Lib implementation.
+
+@copyright
+ Copyright (c) 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
+
+**/
+#include "OverclockingLibrary.h"
+#include "CpuPlatformLibrary.h"
+
+EFI_STATUS
+EFIAPI
+GetVoltageFrequencyItem (
+ OUT VOLTAGE_FREQUENCY_ITEM *VfSettings,
+ OUT UINT32 *LibStatus
+ )
+/**
+ Gets the Voltage and Frequency information for a given CPU domain
+
+ @param[OUT] *VfSettings
+ @param[OUT] *LibStatus
+
+ @retval EFI_STATUS
+**/
+{
+ EFI_STATUS Status;
+ UINT32 CommandId;
+ UINT16 TempVoltageTarget;
+ INT16 TempVoltageOffset;
+ OC_MAILBOX_ITEM VfMsg;
+
+ Status = EFI_SUCCESS;
+
+ ZeroMem(&VfMsg,sizeof(VfMsg));
+ ///
+ /// Convert v/f command to Mailbox command format
+ ///
+ CommandId = OC_LIB_CMD_GET_VOLTAGE_FREQUENCY;
+
+ ConvertToMailboxFormat((VOID *)VfSettings, &VfMsg, CommandId);
+
+ ///
+ /// Read From the OC Library
+ ///
+ Status = MailboxRead(MAILBOX_TYPE_OC, VfMsg.Interface.InterfaceData, &VfMsg.Data, LibStatus);
+
+ ///
+ /// Copy mailbox data to VfSettings
+ ///
+ if ( (Status == EFI_SUCCESS) && (*LibStatus == OC_LIB_COMPLETION_CODE_SUCCESS)) {
+ VfSettings->VfSettings.MaxOcRatio = (UINT8) (VfMsg.Data & MAX_RATIO_MASK);
+ VfSettings->VfSettings.VoltageTargetMode = (UINT8) ( (VfMsg.Data & VOLTAGE_MODE_MASK) >> VOLTAGE_MODE_OFFSET);
+
+ TempVoltageTarget = (UINT16) (VfMsg.Data & VOLTAGE_TARGET_MASK) >> VOLTAGE_TARGET_OFFSET;
+ ConvertVoltageTarget(TempVoltageTarget, &VfSettings->VfSettings.VoltageTarget, CONVERT_TO_BINARY_MILLIVOLT);
+
+ TempVoltageOffset = (INT16)((VfMsg.Data & VOLTAGE_OFFSET_MASK) >> VOLTAGE_OFFSET_OFFSET);
+ ConvertVoltageOffset(TempVoltageOffset, &VfSettings->VfSettings.VoltageOffset, CONVERT_TO_BINARY_MILLIVOLT);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+SetVoltageFrequencyItem (
+ IN VOLTAGE_FREQUENCY_ITEM VfSettings,
+ OUT UINT32 *LibStatus
+ )
+/**
+ Sets the Voltage and Frequency information for a given CPU domain
+
+ @param[IN] *VfSettings
+ @param[OUT] *LibStatus
+
+ @retval EFI_STATUS
+**/
+{
+ EFI_STATUS Status;
+ UINT32 CommandId;
+ OC_MAILBOX_ITEM VfMsg;
+
+ Status = EFI_SUCCESS;
+
+ ///
+ /// Convert v/f Commands to Mailbox command format
+ ///
+ CommandId = OC_LIB_CMD_SET_VOLTAGE_FREQUENCY;
+ ConvertToMailboxFormat((VOID *)&VfSettings, &VfMsg, CommandId);
+
+ ///
+ /// Write the v/f Settings to the OC Mailbox
+ ///
+ Status = MailboxWrite(MAILBOX_TYPE_OC, VfMsg.Interface.InterfaceData, VfMsg.Data, LibStatus);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+GetFivrConfig (
+ OUT GLOBAL_CONFIG_ITEM *FivrConfig,
+ OUT UINT32 *LibStatus
+ )
+/**
+ Get the global FIVR Configuration information
+
+ @param[OUT] *FivrConfig
+ @param[OUT] *LibStatus
+
+ @retval EFI_STATUS
+**/
+{
+ EFI_STATUS Status;
+ UINT32 CommandId;
+ OC_MAILBOX_ITEM FivrMsg;
+
+ Status = EFI_SUCCESS;
+ ZeroMem(&FivrMsg, sizeof(FivrMsg));
+
+ ///
+ /// Convert FIVR message to Mailbox command format
+ ///
+ CommandId = OC_LIB_CMD_GET_GLOBAL_CONFIG;
+ ConvertToMailboxFormat((VOID *)FivrConfig, &FivrMsg, CommandId);
+
+ ///
+ /// Read From the OC Library
+ ///
+ Status = MailboxRead(MAILBOX_TYPE_OC, FivrMsg.Interface.InterfaceData, &FivrMsg.Data, LibStatus);
+
+ ///
+ /// Copy mailbox data to FivrConfig
+ ///
+ if ( (Status == EFI_SUCCESS) && (*LibStatus == OC_LIB_COMPLETION_CODE_SUCCESS)) {
+ FivrConfig->DisableFivrFaults = FivrMsg.Data & FIVR_FAULTS_MASK;
+ FivrConfig->DisableFivrEfficiency = (FivrMsg.Data & FIVR_EFFICIENCY_MASK) >> FIVR_EFFICIENCY_OFFSET;
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+SetFivrConfig (
+ IN GLOBAL_CONFIG_ITEM FivrConfig,
+ OUT UINT32 *LibStatus
+ )
+/**
+ Set the Global FIVR Configuration information
+
+ @param[IN] FivrConfig
+ @param[OUT] *LibStatus
+
+ @retval EFI_STATUS
+**/
+{
+ EFI_STATUS Status;
+ UINT32 CommandId;
+ OC_MAILBOX_ITEM FivrMsg;
+
+ Status = EFI_SUCCESS;
+
+ ///
+ /// Convert FIVR Command to Mailbox command format
+ ///
+ CommandId = OC_LIB_CMD_SET_GLOBAL_CONFIG;
+ ConvertToMailboxFormat((VOID *)&FivrConfig, &FivrMsg, CommandId);
+
+ ///
+ /// Write the FIVR Settings to the OC Mailbox
+ ///
+ Status = MailboxWrite(MAILBOX_TYPE_OC, FivrMsg.Interface.InterfaceData, FivrMsg.Data, LibStatus);
+
+ return Status;
+
+}
+
+EFI_STATUS
+EFIAPI
+GetSvidConfig (
+ OUT SVID_CONFIG_ITEM *SvidConfig,
+ OUT UINT32 *LibStatus
+ )
+/**
+ Get the SVID Configuration information
+
+ @param[OUT] *SvidConfig
+ @param[OUT] *LibStatus
+
+ @retval EFI_STATUS
+**/
+{
+ EFI_STATUS Status;
+ UINT32 CommandId;
+ OC_MAILBOX_ITEM SvidMsg;
+
+ Status = EFI_SUCCESS;
+ ZeroMem(&SvidMsg, sizeof(SvidMsg));
+
+ ///
+ /// Convert SVID message to Mailbox command format
+ ///
+ CommandId = OC_LIB_CMD_GET_SVID_CONFIG;
+ ConvertToMailboxFormat((VOID *)SvidConfig, &SvidMsg, CommandId);
+
+ ///
+ /// Read From the OC Library
+ ///
+ Status = MailboxRead(MAILBOX_TYPE_OC, SvidMsg.Interface.InterfaceData, &SvidMsg.Data, LibStatus);
+
+ ///
+ /// Copy mailbox data to SvidConfig
+ ///
+ if ( (Status == EFI_SUCCESS) && (*LibStatus == OC_LIB_COMPLETION_CODE_SUCCESS)) {
+ SvidConfig->VoltageTarget = (UINT16) SvidMsg.Data & SVID_VOLTAGE_MASK;
+ SvidConfig->SvidDisable = (UINT8) ((SvidMsg.Data & SVID_DISABLE_MASK) >> SVID_DISABLE_OFFSET);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+SetSvidConfig (
+ IN SVID_CONFIG_ITEM SvidConfig,
+ OUT UINT32 *LibStatus
+ )
+/**
+ Set the SVID Configuration information
+
+ @param[IN] SvidConfig
+ @param[OUT] *LibStatus
+
+ @retval EFI_STATUS
+**/
+{
+ EFI_STATUS Status;
+ UINT32 CommandId;
+ OC_MAILBOX_ITEM SvidMsg;
+
+ Status = EFI_SUCCESS;
+
+ ///
+ /// Convert SVID Commands to Mailbox command format
+ ///
+ CommandId = OC_LIB_CMD_SET_SVID_CONFIG;
+ ConvertToMailboxFormat((VOID *)&SvidConfig, &SvidMsg, CommandId);
+
+ ///
+ /// Write the Svid Settings to the OC Mailbox
+ ///
+ Status = MailboxWrite(MAILBOX_TYPE_OC, SvidMsg.Interface.InterfaceData, SvidMsg.Data, LibStatus);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+GetOcCapabilities (
+ OUT OC_CAPABILITIES_ITEM *OcCapabilities,
+ OUT UINT32 *LibStatus
+ )
+/**
+ Get the overclocking capabilities for a given CPU Domain
+
+ @param[OUT] *OcCapabilities
+ @param[OUT] *LibStatus
+
+ @retval EFI_STATUS
+**/
+{
+ EFI_STATUS Status;
+ UINT32 CommandId;
+ OC_MAILBOX_ITEM OcCapsMsg;
+
+ Status = EFI_SUCCESS;
+
+ ZeroMem(&OcCapsMsg,sizeof(OC_MAILBOX_ITEM));
+
+ ///
+ /// Convert OC capabilties message to Mailbox command format
+ ///
+ CommandId = OC_LIB_CMD_GET_OC_CAPABILITIES;
+ ConvertToMailboxFormat((VOID *)OcCapabilities, &OcCapsMsg, CommandId);
+
+ ///
+ /// Read From the OC Library
+ ///
+ Status = MailboxRead(MAILBOX_TYPE_OC, OcCapsMsg.Interface.InterfaceData, &OcCapsMsg.Data, LibStatus);
+
+ ///
+ /// Copy mailbox data to OC Capabilities structure
+ ///
+ if ( (Status == EFI_SUCCESS) && (*LibStatus == OC_LIB_COMPLETION_CODE_SUCCESS)) {
+ OcCapabilities->MaxOcRatioLimit =
+ (UINT8) OcCapsMsg.Data & OC_CAPS_MAX_RATIO_MASK;
+
+ OcCapabilities->RatioOcSupported =
+ (UINT8) ((OcCapsMsg.Data & OC_CAPS_RATIO_SUPPORT_MASK) >> OC_CAPS_RATIO_SUPPORT_OFFSET);
+
+ OcCapabilities->VoltageOverridesSupported =
+ (UINT8) ((OcCapsMsg.Data & OC_CAPS_OVERRIDE_SUPPORT_MASK) >> OC_CAPS_OVERRIDE_SUPPORT_OFFSET);
+
+ OcCapabilities->VoltageOffsetSupported =
+ (UINT8) ((OcCapsMsg.Data & OC_CAPS_OFFSET_SUPPORT_MASK) >> OC_CAPS_OFFSET_SUPPORT_OFFSET);
+ }
+
+ return Status;
+}
+
+VOID
+ConvertVoltageTarget (
+ IN UINT16 InputVoltageTarget,
+ OUT UINT16 *OutputVoltageTarget,
+ IN UINT8 ConversionType
+ )
+/**
+ Converts the input voltage target to the fixed point U12.2.10 Volt format or
+ the Binary millivolts representation based on the ConversionType
+
+@param[IN] InputVoltageTarget
+@param[OUT] *OutputVoltageTarget
+@param[IN] ConversionType - 0:fixed point, 1:Binary millivolts
+**/
+{
+UINT32 Remainder;
+ /// Fixed point representation:
+ ///
+ /// U12.2.10V format
+ /// | | | |
+ /// | | | v
+ /// | | v Exponent
+ /// | v Significand Size
+ /// v Size
+ /// Signed/Unsigned
+ ///
+ /// Float Value = Significand x (Base ^ Exponent)
+ /// (Base ^ Exponent) = 2 ^ 10 = 1024
+ ///
+ Remainder = 0;
+
+ if (InputVoltageTarget == 0) {
+ *OutputVoltageTarget = 0;
+ return;
+ }
+
+ if (ConversionType == CONVERT_TO_FIXED_POINT_VOLTS) {
+ ///
+ /// Input Voltage is in number of millivolts. Clip the input Voltage
+ /// to the max allowed by the fixed point format
+ ///
+ if (InputVoltageTarget > MAX_TARGET_MV)
+ InputVoltageTarget = MAX_TARGET_MV;
+
+ ///
+ /// InputTargetVoltage is the significand in mV. Need to convert to Volts
+ ///
+ *OutputVoltageTarget = (UINT16) DivU64x32Remainder (
+ (UINT64) (InputVoltageTarget * 1024), MILLIVOLTS_PER_VOLT,&Remainder);
+
+ if (Remainder >= 500) {
+ *OutputVoltageTarget += 1;
+ }
+ } else if (ConversionType == CONVERT_TO_BINARY_MILLIVOLT) {
+ ///
+ /// InputVoltage is specified in fixed point representation, need to
+ /// convert to millivolts
+ ///
+ *OutputVoltageTarget = (UINT16) DivU64x32Remainder (
+ (UINT64) (InputVoltageTarget * MILLIVOLTS_PER_VOLT), 1024,&Remainder);
+
+ if (Remainder >= 500) {
+ *OutputVoltageTarget += 1;
+ }
+ }
+
+ return;
+}
+
+VOID
+ConvertVoltageOffset (
+ IN INT16 InputVoltageOffset,
+ OUT INT16 *OutputVoltageOffset,
+ IN UINT8 ConversionType
+ )
+/**
+ Converts the input votlage Offset to the fixed point S11.0.10 Volt format or
+ to Binary illivolts representation based on the ConversionType.
+
+@param[IN] InputVoltageTarget
+@param[OUT] *OutputVoltageTarget
+@param[IN] ConversionType - 0:fixed point, 1:Signed Binary millivolts
+**/
+{
+ BOOLEAN NumIsNegative;
+ UINT32 Remainder;
+ /// Fixed point representation:
+ ///
+ /// S11.0.10V format
+ /// | | | |
+ /// | | | v
+ /// | | v Exponent
+ /// | v Significand Size
+ /// v Size
+ /// Signed/Unsigned
+ ///
+ /// Float Value = Significand x (Base ^ Exponent)
+ /// (Base ^ Exponent) = 2 ^ 10 = 1024
+ ///
+ *OutputVoltageOffset = 0;
+ NumIsNegative = FALSE;
+ Remainder = 0;
+
+ if (InputVoltageOffset == 0) {
+ *OutputVoltageOffset = 0;
+ return;
+ }
+
+ if (ConversionType == CONVERT_TO_FIXED_POINT_VOLTS) {
+ ///
+ /// Input Voltage is in INT16 representation. Check if numenr is negative
+ ///
+ if ( (InputVoltageOffset & INT16_SIGN_BIT_MASK) != 0) {
+ NumIsNegative = TRUE;
+ ///
+ /// Need to 2's complement adjust to make this number positive for
+ /// voltage calculation
+ ///
+ InputVoltageOffset = (~InputVoltageOffset+1) & (INT16_SIGN_BIT_MASK -1);
+ }
+
+ ///
+ /// Clip the input Voltage Offset to 500mv
+ ///
+ if (InputVoltageOffset > MAX_OFFSET_MV) {
+ InputVoltageOffset = MAX_OFFSET_MV;
+ }
+
+ ///
+ /// Convert to fixed point representation
+ ///
+ *OutputVoltageOffset = (UINT16) DivU64x32Remainder (
+ (UINT64) (InputVoltageOffset * 1024), MILLIVOLTS_PER_VOLT,&Remainder);
+
+ if (Remainder >= 500) {
+ *OutputVoltageOffset += 1;
+ }
+
+ if (NumIsNegative) {
+ /// 2's complement back to a negative number
+ *OutputVoltageOffset = ~(*OutputVoltageOffset) + 1;
+ }
+ } else if (ConversionType == CONVERT_TO_BINARY_MILLIVOLT) {
+ ///
+ /// Input Voltage is in fixed point representation. Check if number negative
+ ///
+ if ( (InputVoltageOffset & FIXED_POINT_SIGN_BIT_MASK)!= 0) {
+ NumIsNegative = TRUE;
+ ///
+ /// Need to 2's complement adjust to make this number positive for
+ /// voltage calculation
+ ///
+ InputVoltageOffset = (~InputVoltageOffset+1) & (FIXED_POINT_SIGN_BIT_MASK -1);
+ }
+
+ ///
+ /// Convert to INT16 representation in millivolts
+ ///
+ *OutputVoltageOffset = (UINT16) DivU64x32Remainder (
+ (UINT64) (InputVoltageOffset * MILLIVOLTS_PER_VOLT), 1024,&Remainder);
+
+ if (Remainder >= 500) {
+ *OutputVoltageOffset += 1;
+ }
+
+ if (NumIsNegative) {
+ /// 2's complement back to a negative number
+ *OutputVoltageOffset = ~(*OutputVoltageOffset) + 1;
+ }
+ }
+
+ return;
+}
+
+VOID
+ConvertToMailboxFormat (
+ IN VOID *InputData,
+ OUT OC_MAILBOX_ITEM *MailboxData,
+ IN UINT32 CommandId
+ )
+/**
+ Converts the input data to valid mailbox command format based on CommandID
+
+@param[IN] InputData
+@param[OUT] *MailboxData
+@param[IN] CommandId
+**/
+{
+ VOLTAGE_FREQUENCY_ITEM *VfItem;
+ SVID_CONFIG_ITEM *SvidItem;
+ OC_CAPABILITIES_ITEM *OcCapItem;
+ CORE_RATIO_LIMITS_ITEM *CoreRatioItem;
+ GLOBAL_CONFIG_ITEM *GlobalConfigItem;
+ VF_MAILBOX_COMMAND_DATA VfMailboxCommandData;
+ UINT16 TempVoltage;
+
+ ///
+ /// Initialize local varaibles and mailbox data
+ ///
+ ZeroMem ((UINT32 *)MailboxData, sizeof(OC_MAILBOX_ITEM));
+
+ ///
+ /// Then make a decision based on CommandId how to format
+ ///
+ switch (CommandId) {
+ case OC_LIB_CMD_GET_OC_CAPABILITIES:
+ OcCapItem = (OC_CAPABILITIES_ITEM *) InputData;
+ ///
+ /// OC Capabilities are returned on a per domain basis
+ ///
+ MailboxData->Data = 0;
+ MailboxData->Interface.Fields.CommandCompletion = OC_LIB_CMD_GET_OC_CAPABILITIES;
+ MailboxData->Interface.Fields.Param1 = OcCapItem->DomainId;
+ break;
+
+ case OC_LIB_CMD_GET_PER_CORE_RATIO_LIMIT:
+ CoreRatioItem = (CORE_RATIO_LIMITS_ITEM *) InputData;
+ ///
+ /// Core Ratio Limits are only valid in the IA Core domain
+ ///
+ MailboxData->Data = 0;
+ MailboxData->Interface.Fields.CommandCompletion = OC_LIB_CMD_GET_PER_CORE_RATIO_LIMIT;
+ MailboxData->Interface.Fields.Param1 = OC_LIB_DOMAIN_ID_IA_CORE;
+ MailboxData->Interface.Fields.Param2 = CoreRatioItem->Index;
+ break;
+
+ case OC_LIB_CMD_GET_VOLTAGE_FREQUENCY:
+ VfItem = (VOLTAGE_FREQUENCY_ITEM *) InputData;
+ ///
+ /// Voltage Frequency Settings are on a per domain basis
+ ///
+ MailboxData->Data = 0;
+ MailboxData->Interface.Fields.CommandCompletion = OC_LIB_CMD_GET_VOLTAGE_FREQUENCY;
+ MailboxData->Interface.Fields.Param1 = VfItem->DomainId;
+ break;
+
+ case OC_LIB_CMD_SET_VOLTAGE_FREQUENCY:
+ VfItem = (VOLTAGE_FREQUENCY_ITEM *) InputData;
+ ///
+ /// Voltages are stored in a fixed point format
+ ///
+ VfMailboxCommandData.MaxOcRatio = VfItem->VfSettings.MaxOcRatio;
+
+ TempVoltage = 0;
+ ConvertVoltageTarget(VfItem->VfSettings.VoltageTarget, &TempVoltage, CONVERT_TO_FIXED_POINT_VOLTS);
+ VfMailboxCommandData.VoltageTargetU12 = TempVoltage;
+
+ VfMailboxCommandData.TargetMode = VfItem->VfSettings.VoltageTargetMode;
+
+ TempVoltage = 0;
+ ConvertVoltageOffset(VfItem->VfSettings.VoltageOffset, (INT16 *) &TempVoltage, CONVERT_TO_FIXED_POINT_VOLTS);
+ VfMailboxCommandData.VoltageOffsetS11 = TempVoltage;
+
+ CopyMem(&MailboxData->Data, &VfMailboxCommandData, sizeof(VfMailboxCommandData));
+ MailboxData->Interface.Fields.CommandCompletion = OC_LIB_CMD_SET_VOLTAGE_FREQUENCY;
+ MailboxData->Interface.Fields.Param1 = VfItem->DomainId;
+ break;
+
+ case OC_LIB_CMD_GET_SVID_CONFIG:
+ MailboxData->Data = 0;
+ MailboxData->Interface.Fields.CommandCompletion = OC_LIB_CMD_GET_SVID_CONFIG;
+ MailboxData->Interface.Fields.Param1 = 0;
+ break;
+
+ case OC_LIB_CMD_SET_SVID_CONFIG:
+ SvidItem = (SVID_CONFIG_ITEM *) InputData;
+ ConvertVoltageTarget(SvidItem->VoltageTarget, &TempVoltage, CONVERT_TO_FIXED_POINT_VOLTS);
+ MailboxData->Data = TempVoltage | (SvidItem->SvidDisable << SVID_DISABLE_OFFSET);
+ MailboxData->Interface.Fields.CommandCompletion = OC_LIB_CMD_SET_SVID_CONFIG;
+ MailboxData->Interface.Fields.Param1 = 0;
+ break;
+
+ case OC_LIB_CMD_GET_GLOBAL_CONFIG:
+ MailboxData->Data = 0;
+ MailboxData->Interface.Fields.CommandCompletion = OC_LIB_CMD_GET_GLOBAL_CONFIG;
+ MailboxData->Interface.Fields.Param1 = 0;
+ break;
+
+ case OC_LIB_CMD_SET_GLOBAL_CONFIG:
+ GlobalConfigItem = (GLOBAL_CONFIG_ITEM *) InputData;
+ MailboxData->Data =
+ (GlobalConfigItem->DisableFivrFaults & BIT0_MASK) |
+ ((GlobalConfigItem->DisableFivrEfficiency & BIT0_MASK) << FIVR_EFFICIENCY_OFFSET);
+ MailboxData->Interface.Fields.CommandCompletion = OC_LIB_CMD_SET_GLOBAL_CONFIG;
+ MailboxData->Interface.Fields.Param1 = 0;
+ break;
+
+ default:
+ DEBUG ((EFI_D_ERROR, "(OC MAILBOX) Unknown Command ID\n"));
+
+ break;
+
+ }
+
+}
+
diff --git a/ReferenceCode/Haswell/Library/OverclockingLib/OverclockingLibrary.h b/ReferenceCode/Haswell/Library/OverclockingLib/OverclockingLibrary.h
new file mode 100644
index 0000000..fd32d1f
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/OverclockingLib/OverclockingLibrary.h
@@ -0,0 +1,352 @@
+/** @file
+ Header file for Cpu Platform Lib implementation.
+
+@copyright
+ Copyright (c) 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
+**/
+#ifndef _OVERCLOCKING_LIBRARY_H_
+#define _OVERCLOCKING_LIBRARY_H_
+
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueBase.h"
+#endif
+
+//
+// OC Mailbox MSR
+//
+#define MSR_OC_MAILBOX 0x00000150
+#define OC_LIB_WAIT_TIMEOUT 5000 ///< 5 milliseconds
+
+//
+// OC Mailbox commands
+//
+#define OC_LIB_CMD_GET_OC_CAPABILITIES 0x01
+#define OC_LIB_CMD_GET_PER_CORE_RATIO_LIMIT 0x02
+#define OC_LIB_CMD_GET_VOLTAGE_FREQUENCY 0x10
+#define OC_LIB_CMD_SET_VOLTAGE_FREQUENCY 0x11
+#define OC_LIB_CMD_GET_SVID_CONFIG 0x12
+#define OC_LIB_CMD_SET_SVID_CONFIG 0x13
+#define OC_LIB_CMD_GET_GLOBAL_CONFIG 0x14
+#define OC_LIB_CMD_SET_GLOBAL_CONFIG 0x15
+
+//
+// OC Mailbox completion codes
+//
+#define OC_LIB_COMPLETION_CODE_SUCCESS 0x00
+#define OC_LIB_COMPLETION_CODE_OC_LOCKED 0x01
+#define OC_LIB_COMPLETION_CODE_INVALID_DOMAIN 0x02
+#define OC_LIB_COMPLETION_CODE_MAX_RATIO_EXCEEDED 0x03
+#define OC_LIB_COMPLETION_CODE_MAX_VOLTAGE_EXCEEDED 0x04
+#define OC_LIB_COMPLETION_CODE_OC_NOT_SUPPORTED 0x05
+#define OC_LIB_COMPLETION_CODE_WRITE_FAILED 0x06
+#define OC_LIB_COMPLETION_CODE_READ_FAILED 0x07
+
+//
+// Domain ID definitions
+//
+#define OC_LIB_DOMAIN_ID_IA_CORE 0x00
+#define OC_LIB_DOMAIN_ID_GT 0x01
+#define OC_LIB_DOMAIN_ID_CLR 0x02
+#define OC_LIB_DOMAIN_ID_UNCORE 0x03
+#define OC_LIB_DOMAIN_ID_IOA 0x04
+#define OC_LIB_DOMAIN_ID_IOD 0x05
+
+//
+// Bit 10 is the S11.0.10V sign bit
+//
+#define FIXED_POINT_SIGN_BIT_MASK 0x0400
+#define INT16_SIGN_BIT_MASK 0x8000
+
+//
+// Voltage Conversion defines
+//
+#define MILLIVOLTS_PER_VOLT 1000
+#define MAX_TARGET_MV 4095
+#define MAX_OFFSET_MV 500
+
+#define CONVERT_TO_FIXED_POINT_VOLTS 0
+#define CONVERT_TO_BINARY_MILLIVOLT 1
+
+//
+// Masks and offsets
+//
+#define BIT0_MASK 0x1
+#define MAX_RATIO_MASK 0x000000FF
+#define VOLTAGE_TARGET_MASK 0x000FFF00
+#define VOLTAGE_TARGET_OFFSET 8
+#define VOLTAGE_MODE_MASK 0x00100000
+#define VOLTAGE_MODE_OFFSET 20
+#define VOLTAGE_OFFSET_MASK 0xFFE00000
+#define VOLTAGE_OFFSET_OFFSET 21
+
+#define SVID_DISABLE_MASK 0x80000000
+#define SVID_DISABLE_OFFSET 31
+#define SVID_VOLTAGE_MASK 0x00000FFF
+
+#define FIVR_FAULTS_MASK 0x00000001
+#define FIVR_EFFICIENCY_MASK 0x00000002
+#define FIVR_EFFICIENCY_OFFSET 1
+
+#define OC_CAPS_MAX_RATIO_MASK 0x000000FF
+#define OC_CAPS_RATIO_SUPPORT_MASK 0x00000100
+#define OC_CAPS_RATIO_SUPPORT_OFFSET 8
+#define OC_CAPS_OVERRIDE_SUPPORT_MASK 0x00000200
+#define OC_CAPS_OVERRIDE_SUPPORT_OFFSET 9
+#define OC_CAPS_OFFSET_SUPPORT_MASK 0x00000400
+#define OC_CAPS_OFFSET_SUPPORT_OFFSET 10
+
+//
+// Voltage offset definitions
+//
+#define OC_LIB_OFFSET_ADAPTIVE 0
+#define OC_LIB_OFFSET_OVERRIDE 1
+#define OC_LIB_VOLTAGE_DO_NOT_UPDATE 0xFFFF
+
+///
+/// OC Library structures
+///
+typedef struct {
+ UINT32 CommandData;
+ UINT8 CommandCompletion : 8;
+ UINT8 Param1 : 8;
+ UINT8 Param2 : 8;
+ UINT8 Reserved : 7;
+ UINT8 RunBusy : 1;
+} OC_LIBRARY_COMMAND;
+
+typedef union _OC_MAILBOX_COMMAND {
+ UINT32 InterfaceData;
+ struct {
+ UINT8 CommandCompletion : 8;
+ UINT8 Param1 : 8;
+ UINT8 Param2 : 8;
+ UINT8 Reserved : 7;
+ UINT8 RunBusy : 1;
+ } Fields;
+} OC_MAILBOX_COMMAND;
+
+typedef struct _OC_MAILBOX_ITEM {
+ UINT32 Data;
+ OC_MAILBOX_COMMAND Interface;
+} OC_MAILBOX_ITEM;
+
+typedef struct {
+ UINT8 MaxOcRatio;
+ UINT8 VoltageTargetMode;
+ UINT16 VoltageTarget;
+ INT16 VoltageOffset;
+} VOLTAGE_FREQUENCY_SETTINGS;
+
+typedef struct {
+ VOLTAGE_FREQUENCY_SETTINGS VfSettings;
+ UINT8 DomainId;
+} VOLTAGE_FREQUENCY_ITEM;
+
+typedef enum {
+ IaCore,
+ Gt,
+ Clr,
+ Uncore
+} CPU_DOMAIN_ID;
+
+typedef struct {
+ UINT16 VoltageTarget;
+ BOOLEAN SvidDisable;
+} SVID_CONFIG_ITEM;
+
+typedef struct {
+ UINT8 MaxOcRatioLimit;
+ BOOLEAN RatioOcSupported;
+ BOOLEAN VoltageOverridesSupported;
+ BOOLEAN VoltageOffsetSupported;
+ UINT8 DomainId;
+} OC_CAPABILITIES_ITEM;
+
+typedef struct {
+ UINT8 MaxOcRatioLimit1C;
+ UINT8 MaxOcRatioLimit2C;
+ UINT8 MaxOcRatioLimit3C;
+ UINT8 MaxOcRatioLimit4C;
+ UINT8 Index;
+} CORE_RATIO_LIMITS_ITEM;
+
+typedef struct {
+ UINT8 DisableFivrFaults;
+ UINT8 DisableFivrEfficiency;
+} GLOBAL_CONFIG_ITEM;
+
+typedef struct {
+ UINT32 MaxOcRatio : 8;
+ UINT32 VoltageTargetU12 : 12;
+ UINT32 TargetMode : 1;
+ UINT32 VoltageOffsetS11 : 11;
+} VF_MAILBOX_COMMAND_DATA;
+
+///
+/// OC Library Function Prototypes
+///
+EFI_STATUS
+EFIAPI GetVoltageFrequencyItem (
+ OUT VOLTAGE_FREQUENCY_ITEM *VfSettings,
+ OUT UINT32 *LibStatus
+ )
+/**
+ Gets the Voltage and Frequency information for a given CPU domain
+
+ @param[OUT] *VfSettings
+ @param[OUT] *LibStatus
+
+ @retval EFI_STATUS
+**/
+;
+
+EFI_STATUS
+EFIAPI SetVoltageFrequencyItem (
+ IN VOLTAGE_FREQUENCY_ITEM VfSettings,
+ OUT UINT32 *LibStatus
+ )
+/**
+ Sets the Voltage and Frequency information for a given CPU domain
+
+ @param[IN] *VfSettings
+ @param[OUT] *LibStatus
+
+ @retval EFI_STATUS
+**/
+;
+
+EFI_STATUS
+EFIAPI GetFivrConfig (
+ OUT GLOBAL_CONFIG_ITEM *FivrConfig,
+ OUT UINT32 *LibStatus
+ )
+/**
+ Get the global FIVR Configuration information
+
+ @param[OUT] *FivrConfig
+ @param[OUT] *LibStatus
+
+ @retval EFI_STATUS
+**/
+;
+
+EFI_STATUS
+EFIAPI SetFivrConfig (
+ IN GLOBAL_CONFIG_ITEM FivrConfig,
+ OUT UINT32 *LibStatus
+ )
+/**
+ Set the Global FIVR Configuration information
+
+ @param[IN] FivrConfig
+ @param[OUT] *LibStatus
+
+ @retval EFI_STATUS
+**/
+;
+
+EFI_STATUS
+EFIAPI GetSvidConfig (
+ OUT SVID_CONFIG_ITEM *SvidConfig,
+ OUT UINT32 *LibStatus
+ )
+/**
+ Get the SVID Configuration information
+
+ @param[OUT] *SvidConfig
+ @param[OUT] *LibStatus
+
+ @retval EFI_STATUS
+**/
+;
+
+EFI_STATUS
+EFIAPI SetSvidConfig (
+ IN SVID_CONFIG_ITEM SvidConfig,
+ OUT UINT32 *LibStatus
+ )
+/**
+ Set the SVID Configuration information
+
+ @param[IN] SvidConfig
+ @param[OUT] *LibStatus
+
+ @retval EFI_STATUS
+**/
+;
+
+EFI_STATUS
+EFIAPI GetOcCapabilities (
+ OUT OC_CAPABILITIES_ITEM *OcCapabilities,
+ OUT UINT32 *LibStatus
+ )
+/**
+ Get the overclocking capabilities for a given CPU Domain
+
+ @param[OUT] *OcCapabilities
+ @param[OUT] *LibStatus
+
+ @retval EFI_STATUS
+**/
+;
+
+VOID
+ConvertVoltageTarget (
+ IN UINT16 InputVoltageTarget,
+ OUT UINT16 *OutputVoltageTarget,
+ IN UINT8 ConversionType
+ )
+/**
+ Converts the input voltage target to the fixed point U12.2.10 Volt format or
+ the Binary millivolts representation based on the ConversionType
+
+@param[IN] InputVoltageTarget
+@param[OUT] *OutputVoltageTarget
+@param[IN] ConversionType - 0:fixed point, 1:Binary millivolts
+**/
+;
+
+VOID
+ConvertVoltageOffset (
+ IN INT16 InputVoltageOffset,
+ OUT INT16 *OutputVoltageOffset,
+ IN UINT8 ConversionType
+ )
+/**
+ Converts the input votlage Offset to the fixed point S11.0.10 Volt format or
+ to Binary illivolts representation based on the ConversionType.
+
+@param[IN] InputVoltageTarget
+@param[OUT] *OutputVoltageTarget
+@param[IN] ConversionType - 0:fixed point, 1:Signed Binary millivolts
+**/
+;
+
+VOID
+ConvertToMailboxFormat (
+ IN VOID *InputData,
+ OUT OC_MAILBOX_ITEM *MailboxData,
+ IN UINT32 CommandId
+ )
+/**
+ Converts the input data to valid mailbox command format based on CommandID
+
+@param[IN] InputData
+@param[OUT] *MailboxData
+@param[IN] CommandId
+**/
+;
+
+#endif
diff --git a/ReferenceCode/Haswell/Library/ThunkLib.cif b/ReferenceCode/Haswell/Library/ThunkLib.cif
new file mode 100644
index 0000000..f8eda34
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib.cif
@@ -0,0 +1,13 @@
+<component>
+ name = "ThunkLib"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\Library\"
+ RefName = "ThunkLib"
+[files]
+"ThunkLib.sdl"
+"ThunkLib.mak"
+"ThunkLib\ThunkLib.inf"
+[parts]
+"ThunkLibIa32"
+"ThunkLibx64"
+<endComponent>
diff --git a/ReferenceCode/Haswell/Library/ThunkLib.mak b/ReferenceCode/Haswell/Library/ThunkLib.mak
new file mode 100644
index 0000000..ead3c5e
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib.mak
@@ -0,0 +1,40 @@
+# MAK file for the ModulePart:ThunkLib
+ThunkLib_x64_OBJECTS =\
+$(BUILD_DIR)\ReferenceCode\IvyBridgeRc\Library\ThunkLib\x64\x86Thunk.obj\
+$(BUILD_DIR)\ReferenceCode\IvyBridgeRc\Library\ThunkLib\x64\Thunk16.obj\
+$(BUILD_DIR)\ReferenceCode\IvyBridgeRc\Library\ThunkLib\x64\FxSave.obj\
+$(BUILD_DIR)\ReferenceCode\IvyBridgeRc\Library\ThunkLib\x64\FxRestore.obj
+
+ThunkLib_IA32_OBJECTS =\
+$(BUILD_DIR)\IA32\ReferenceCode\IvyBridgeRc\Library\ThunkLib\Ia32\x86Thunk.obj\
+$(BUILD_DIR)\IA32\ReferenceCode\IvyBridgeRc\Library\ThunkLib\Ia32\Thunk16.obj
+
+ThunkLib_PORCESSOR_Ia32_CIF=$(ThunkLib_DIR)\ThunkLib\Ia32\ThunkLibIa32.cif
+ThunkLib_PORCESSOR_x64_CIF=$(ThunkLib_DIR)\ThunkLib\x64\ThunkLibx64.cif
+
+$(ThunkLib_LIB) : ThunkLib
+
+ThunkLib : $(BUILD_DIR)\ThunkLib.mak ThunkLibBin
+
+#-!IF "$(PROCESSOR)"=="x64"
+$(BUILD_DIR)\ThunkLib.mak : $(ThunkLib_DIR)\$(@B).cif $(ThunkLib_DIR)\$(@B).mak $(BUILD_RULES) $(ThunkLib_PORCESSOR_Ia32_CIF) $(ThunkLib_PORCESSOR_x64_CIF)
+ $(CIF2MAK) $(ThunkLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) $(ThunkLib_PORCESSOR_Ia32_CIF) $(ThunkLib_PORCESSOR_x64_CIF)
+#-!ELSE
+#-$(BUILD_DIR)\ThunkLib.mak : $(ThunkLib_DIR)\$(@B).cif $(ThunkLib_DIR)\$(@B).mak $(BUILD_RULES) $(ThunkLib_PORCESSOR_CIF)
+#- $(CIF2MAK) $(ThunkLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) $(ThunkLib_PORCESSOR_CIF)
+#-!ENDIF
+
+ThunkLibBin :
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ BUILD_DIR=$(BUILD_DIR)\
+ /f $(BUILD_DIR)\ThunkLib.mak all\
+ "MY_INCLUDES=$(EDK_INCLUDES) $(EdkIIGlueLib_INCLUDES) $(PROJECT_CPU_INCLUDES)" \
+ TYPE=LIBRARY "PARAMETERS=LIBRARY_NAME=$$(ThunkLib_LIB)"\
+ "OBJECTS=$(ThunkLib_x64_OBJECTS)"
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ BUILD_DIR=$(BUILD_DIR)\IA32\
+ /f $(BUILD_DIR)\ThunkLib.mak all\
+ "MY_INCLUDES=$(EDK_INCLUDES) $(EdkIIGlueLib_INCLUDES) $(PROJECT_CPU_INCLUDES)" \
+ TYPE=PEI_LIBRARY "PARAMETERS=LIBRARY_NAME=$$(ThunkLib_LIB)"\
+ "OBJECTS=$(ThunkLib_IA32_OBJECTS)"
+
diff --git a/ReferenceCode/Haswell/Library/ThunkLib.sdl b/ReferenceCode/Haswell/Library/ThunkLib.sdl
new file mode 100644
index 0000000..e56aae4
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib.sdl
@@ -0,0 +1,26 @@
+TOKEN
+ Name = ThunkLib_SUPPORT
+ Value = "1"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+ Help = "Main switch to enable ThunkLib support in Project"
+End
+
+TOKEN
+ Name = "ThunkLib_LIB"
+ Value = "$$(LIB_BUILD_DIR)\ThunkLib.lib"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+PATH
+ Name = "ThunkLib_DIR"
+End
+
+MODULE
+ Help = "Includes ThunkLib.mak to Project"
+ File = "ThunkLib.mak"
+End
+
diff --git a/ReferenceCode/Haswell/Library/ThunkLib/Ia32/Thunk16.asm b/ReferenceCode/Haswell/Library/ThunkLib/Ia32/Thunk16.asm
new file mode 100644
index 0000000..af9d34c
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib/Ia32/Thunk16.asm
@@ -0,0 +1,238 @@
+;/*++
+; 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) 2006 - 2011 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:
+;
+; Thunk.asm
+;
+; Abstract:
+;
+; Real mode thunk
+;
+;------------------------------------------------------------------------------
+
+ .686p
+ .model flat,C
+ .const
+
+EXTERNDEF mCode16Size:DWORD
+mCode16Size DD _Code16End - _Code16Addr
+
+ .data
+ ALIGN 10h
+
+NullSegSel DQ 0
+_16CsSegSel LABEL QWORD
+ DW -1
+ DW 0
+ DB 0
+ DB 9Bh
+ DB 8Fh ; 16-bit segment, 4GB limit
+ DB 0
+;_16DsSegSel LABEL QWORD
+; DW -1
+; DW 0
+; DB 0
+; DB 93h
+; DB 8Fh ; 16-bit segment, 4GB limit
+; DB 0
+_16Gdtr LABEL FWORD
+ DW $ - offset NullSegSel - 1
+ DD offset NullSegSel
+
+ .code
+
+IA32_REGS STRUC 4t
+_EDI DD ?
+_ESI DD ?
+_EBP DD ?
+_ESP DD ?
+_EBX DD ?
+_EDX DD ?
+_ECX DD ?
+_EAX DD ?
+_DS DW ?
+_ES DW ?
+_FS DW ?
+_GS DW ?
+_EFLAGS DD ?
+_EIP DD ?
+_CS DW ?
+_SS DW ?
+IA32_REGS ENDS
+
+_STK16 STRUC 1t
+RetEip DD ?
+RetCs DW ?
+ThunkFlags DW ?
+SavedGdtr FWORD ?
+Resvd1 DW ?
+SavedCr0 DD ?
+SavedCr4 DD ?
+_STK16 ENDS
+
+; IA32_REGISTER_SET *
+; EFIAPI
+; _Thunk16 (
+; IN OUT IA32_REGISTER_SET *RegisterSet,
+; IN UINT32 ThunkFlags,
+; IN UINT32 RealModeCs
+; );
+_Thunk16 PROC USES DS ES FS GS EDI ESI EBP EBX EDX ECX ; 10 dwords will be pushed
+ mov ebp, esp
+ add ebp, 40
+ mov ORG_SS, ss ; preserve SS & ESP
+ mov ORG_ESP, esp
+
+ mov esi, [ebp + 4] ; esi <- RegisterSet
+ movzx edx, (IA32_REGS ptr [esi])._SS ; find 16-bit stack linear address
+ shl edx, 4
+ add edx, (IA32_REGS ptr [esi])._ESP
+ add edx, - sizeof (IA32_REGS) - sizeof (_STK16) ; edx <- 16-bit stack linear address
+
+ mov edi, edx ; [RealMode.IA32_REGS] <- RegisterSet
+ push sizeof (IA32_REGS) / 4
+ pop ecx
+ rep movsd
+ lea eax, @F ; [RealMode._STK16.RetEip] <- ReturnOffset
+ stosd
+ mov eax, cs ; [RealMode._STK16.RetCs] <- ReturnSegment
+ stosw
+ mov eax, [ebp + 8] ; [RealMode._STK16.ThunkFlags] <- ThunkFlags
+ stosw
+ sgdt dword ptr [edi] ; [RealMode._STK16.SavedGdtr] <- GDTR
+ add edi, 8
+ mov eax, cr0 ; [RealMode._STK16.SavedCr0] <- CR0
+ stosd
+ mov esi, eax ; esi <- CR0 to set
+ and esi, 07FFFFFFEh ; clear BIT[24, 0]: PE & PG bits
+ mov eax, cr4 ; [RealMode._STK16.SavedCr4] <- CR4
+ stosd
+
+ push word ptr [ebp + 12] ; [STACK] <- RealModeCs, far jump address for into RealMode
+ pushw 0
+ pushd 8 ; transfer program control to a readable segment that has a limit of 64KB
+ pushd offset @16Bit
+ mov edi, edx ; edi <- 16-bit stack linear address
+
+ sidt fword ptr [ebp + 8] ; save IDTR
+ lgdt _16Gdtr
+ retf
+@16Bit:
+ mov cr0, esi ; disable PE & PG
+; db 066h
+; mov ecx, 0C0000080h
+; rdmsr
+; and ah, NOT 1
+; wrmsr ; clear LME bit
+ mov eax, cr4
+ and al, not 030h ; clear PAE & PSE
+ mov cr4, eax
+ retf
+@@:
+ xor eax, eax
+ mov eax, ss
+ shl eax, 4
+ add eax, esp ; [EAX] <- RegisterSet after x86 call..to return the execution result
+ mov ss, cs:word ptr [ORG_SS] ; restore SS & ESP
+ mov esp, cs:dword ptr [ORG_ESP]
+ lidt fword ptr [ebp + 8] ; restore IDTR
+
+ ret
+
+ORG_SS DW ?
+ORG_ESP DD ?
+
+_Thunk16 ENDP
+
+ ALIGN 10h
+
+; VOID
+; EFIAPI
+; _Code16Addr (
+; VOID
+; );
+_Code16Addr PROC
+_Code16Addr ENDP
+
+; Input: EDI <- 16-bit stack linear address
+RealMode PROC
+ db 066h ; movzx esp, di
+ movzx esp, di
+ db 033h, 0FFh ; xor di, di
+ db 066h ; shr edi, 4
+ shr edi, 4
+ mov ss, di ; mov ss, di
+
+ db 02Eh, 00Fh, 001, 01Eh ; lidt cs:[_16Idtr]
+ dw (_16Idtr - _Code16Addr)
+ db 066h ; popad
+ popa
+ pop ds
+ pop es
+ pop fs
+ pop gs
+ add esp, 4 ; skip EFLAGS
+
+ ; test if EFLAGS with _THUNK_INTERRUPT
+ db 067h, 00F7h, 044h, 024h, 00Eh, 001h, 000h ; test [esp + 0Eh]
+ jz @F
+ db 09Ch ; pushf
+@@:
+ push cs
+ db 068h ; pushw
+ dw (@FarCallRet - _Code16Addr)
+ jz @F
+ db 066h, 067h
+ jmp fword ptr [esp + 6]
+@@:
+ db 066h, 067h
+ jmp fword ptr [esp + 4]
+@FarCallRet:
+ pushf ; pushfd actually
+ push gs
+ push fs
+ push es
+ push ds
+ db 066h ; pushad
+ pusha
+ cli
+
+ db 066h, 067h
+ lgdt (_STK16 ptr [esp + sizeof(IA32_REGS)]).SavedGdtr
+ db 066h, 067h
+ mov eax, (_STK16 ptr [esp + sizeof(IA32_REGS)]).SavedCr4
+ mov cr4, eax
+; db 066h
+; mov ecx, 0C0000080h
+; rdmsr
+; or ah, 1
+; wrmsr ; set LME
+ db 066h, 067h
+ mov eax, (_STK16 ptr [esp + sizeof(IA32_REGS)]).SavedCr0
+ mov cr0, eax
+ db 066h, 067h
+ jmp fword ptr (_STK16 ptr [esp + sizeof(IA32_REGS)]).RetEip
+
+RealMode ENDP
+
+_16Idtr FWORD (1 shl 10) - 1
+
+_Code16End:
+
+ END
diff --git a/ReferenceCode/Haswell/Library/ThunkLib/Ia32/ThunkLibIa32.cif b/ReferenceCode/Haswell/Library/ThunkLib/Ia32/ThunkLibIa32.cif
new file mode 100644
index 0000000..e0204e7
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib/Ia32/ThunkLibIa32.cif
@@ -0,0 +1,9 @@
+<component>
+ name = "ThunkLib Ia32"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\Library\ThunkLib\Ia32"
+ RefName = "ThunkLibIa32"
+[files]
+"x86Thunk.c"
+"Thunk16.asm"
+<endComponent>
diff --git a/ReferenceCode/Haswell/Library/ThunkLib/Ia32/x86Thunk.c b/ReferenceCode/Haswell/Library/ThunkLib/Ia32/x86Thunk.c
new file mode 100644
index 0000000..ec1045f
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib/Ia32/x86Thunk.c
@@ -0,0 +1,245 @@
+/** @file
+ Real Mode Thunk Functions for IA32 and X64
+
+@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 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
+
+**/
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "ThunkLib.h"
+#define _THUNK_INTERRUPT 0x10000
+#endif
+
+extern const UINTN mCode16Size;
+
+extern
+IA32_REGISTER_SET *
+EFIAPI
+_Thunk16 (
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 ThunkFlags,
+ IN UINT32 RealModeCs
+ );
+
+extern
+VOID
+EFIAPI
+_Code16Addr (
+ VOID
+ );
+
+/**
+ Returns the properties of this real mode thunk implementation. Currently
+ there are 2 properties has been defined, the minimum real mode buffer size
+ and the minimum stack size.
+
+ @param[in] MinimumStackSize - The minimum size required for a 16-bit stack.
+
+ @retval The minimum size of the real mode buffer needed by this thunk implementation
+ @retval is returned.
+**/
+UINTN
+EFIAPI
+R8AsmThunk16GetProperties (
+ OUT UINTN *MinimumStackSize
+ )
+{
+ ///
+ /// This size should be large enough to hold the register set as well as saved
+ /// CPU contexts including GDTR, CR0 and CR4
+ ///
+ if (MinimumStackSize) {
+ *MinimumStackSize = sizeof (IA32_REGISTER_SET) + 0x200;
+ }
+
+ return mCode16Size;
+}
+
+/**
+ Tell this real mode thunk implementation the address and size of the real
+ mode buffer needed.
+
+ @param[in] ThunkContext - The thunk context whose properties to set.
+ @param[in] RealModeBuffer - The address of the buffer allocated by caller. It should be
+ aligned on a 16-byte boundary.
+ This buffer must be in identity mapped pages.
+ @param[in] BufferSize - The size of RealModeBuffer. Must be larger than the minimum
+ size required as returned by R8AsmThunk16GetProperties().
+**/
+THUNK16_CONTEXT *
+EFIAPI
+R8AsmThunk16SetProperties (
+ OUT THUNK16_CONTEXT *ThunkContext,
+ IN VOID *RealModeBuffer,
+ IN UINTN BufferSize
+ )
+{
+ BufferSize &= ~3;
+
+ ASSERT ((UINTN) RealModeBuffer < 0x100000);
+ ASSERT (((UINTN) RealModeBuffer & 0xf) == 0);
+ ASSERT (BufferSize >= mCode16Size);
+
+ ThunkContext->RealModeBuffer = (UINT32) ((UINTN) RealModeBuffer);
+ ThunkContext->DefaultStack = (UINT32) (ThunkContext->RealModeBuffer + BufferSize);
+ CopyMem (RealModeBuffer, (VOID *) (UINTN) _Code16Addr, mCode16Size);
+ return ThunkContext;
+}
+
+/**
+ Reset all internal states to their initial values. The caller should not
+ release the real mode buffer until after a call to this function.
+
+ @param[in] ThunkContext - The thunk context to destroy.
+**/
+VOID
+EFIAPI
+R8AsmThunk16Destroy (
+ IN OUT THUNK16_CONTEXT *ThunkContext
+ )
+{
+ ThunkContext->RealModeBuffer = 0;
+}
+
+/**
+ Do the 16-bit thunk code.
+
+ NOTE: This function must be called on TPL_HIGH_LEVEL or with interrupts
+ disabled because of GDTR and IDTR manipulations.
+ This function must be placed in identity mapped pages.
+
+ @param[in] ThunkContext - Thunk context to use.
+ @param[in] RegisterSet - CPU registers would be set to the values contained in this
+ structure before making the far call. Then CPU registers are
+ copied back to this structure.
+ SS:ESP points to the real mode stack if THUNK_USER_STACK is
+ set on input, otherwise ignored.
+ EFlages is ignored on input.
+ On output, values of CS, EIP, SS and ESP should be ignored.
+ @param[in] ThunkFlags - 2 flags have currently been defined, THUNK_SAVE_FP_STATE and
+ THUNK_USER_STACK.
+ THUNK_SAVE_FP_STATE - FPU state would be saved/restored
+ before/after calling real mode code.
+ THUNK_USER_STACK - The stack specified by SS:ESP would be
+ used instead of the default stack.
+
+ @retval RegisterSet is returned.
+**/
+static
+IA32_REGISTER_SET *
+EFIAPI
+R8AsmThunk16 (
+ IN THUNK16_CONTEXT *ThunkContext,
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 ThunkFlags
+ )
+{
+ ASSERT (ThunkContext->RealModeBuffer != 0);
+ ASSERT ((ThunkContext->RealModeBuffer & 0xf) == 0);
+
+ if (!(ThunkFlags & THUNK_USER_STACK)) {
+ RegisterSet->E.ESP = (UINT16) ThunkContext->DefaultStack;
+ RegisterSet->E.SS = (UINT16) ((ThunkContext->DefaultStack >> 4) & 0xf000);
+ }
+
+ ASSERT ((RegisterSet->E.ESP >> 16) == 0);
+
+ CopyMem (
+ RegisterSet,
+ _Thunk16 (RegisterSet,
+ (UINT16) (ThunkFlags >> 16),
+ ThunkContext->RealModeBuffer >> 4),
+ sizeof (IA32_REGISTER_SET)
+ );
+
+ return RegisterSet;
+}
+
+/**
+ Make a far call to 16-bit code.
+
+ NOTE: This function must be called on TPL_HIGH_LEVEL or with interrupts
+ disabled because of GDTR and IDTR manipulations.
+ This function must be placed in identity mapped pages.
+
+ @param[in] ThunkContext - Thunk context to use.
+ @param[in] RegisterSet - CPU registers would be set to the values contained in this
+ structure before making the far call. Then CPU registers are
+ copied back to this structure.
+ CS:EIP points to the real mode code being called on input.
+ SS:ESP points to the real mode stack if THUNK_USER_STACK is
+ set on input, otherwise ignored.
+ EFlages is ignored on input.
+ On output, values of CS, EIP, SS and ESP should be ignored.
+ @param[in] Flags - 2 flags have currently been defined, THUNK_SAVE_FP_STATE and
+ THUNK_USER_STACK.
+ THUNK_SAVE_FP_STATE - FPU state would be saved/restored
+ before/after calling real mode code.
+ THUNK_USER_STACK - The stack specified by SS:ESP would be
+ used instead of the default stack.
+
+ @retval RegisterSet is returned.
+**/
+IA32_REGISTER_SET *
+EFIAPI
+R8AsmThunk16FarCall86 (
+ IN THUNK16_CONTEXT *ThunkContext,
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 Flags
+ )
+{
+ return R8AsmThunk16 (ThunkContext, RegisterSet, Flags);
+}
+
+/**
+ Invoke a 16-bit interrupt handler.
+
+ NOTE: This function must be called on TPL_HIGH_LEVEL or with interrupts
+ disabled because of GDTR and IDTR manipulations.
+ This function must be placed in identity mapped pages.
+
+ @param[in] ThunkContext - Thunk context to use.
+ @param[in] IntNumber - The ordinal of the interrupt handler ranging from 0 to 255.
+ @param[in] RegisterSet - CPU registers would be set to the values contained in this
+ structure before making the far call. Then CPU registers are
+ copied back to this structure.
+ SS:ESP points to the real mode stack if THUNK_USER_STACK is
+ set on input, otherwise ignored.
+ EFlages is ignored on input.
+ On output, values of CS, EIP, SS and ESP should be ignored.
+ @param[in] Flags - 2 flags have currently been defined, THUNK_SAVE_FP_STATE and
+ THUNK_USER_STACK.
+ THUNK_SAVE_FP_STATE - FPU state would be saved/restored
+ before/after calling real mode code.
+ THUNK_USER_STACK - The stack specified by SS:ESP would be
+ used instead of the default stack.
+
+ @retval RegisterSet is returned.
+**/
+IA32_REGISTER_SET *
+EFIAPI
+R8AsmThunk16Int86 (
+ IN THUNK16_CONTEXT *ThunkContext,
+ IN UINT8 IntNumber,
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 Flags
+ )
+{
+ RegisterSet->E.Eip = (UINT16) ((UINT32 *) NULL)[IntNumber];
+ RegisterSet->E.CS = (UINT16) (((UINT32 *) NULL)[IntNumber] >> 16);
+ return R8AsmThunk16 (ThunkContext, RegisterSet, Flags | _THUNK_INTERRUPT);
+}
diff --git a/ReferenceCode/Haswell/Library/ThunkLib/ThunkLib.inf b/ReferenceCode/Haswell/Library/ThunkLib/ThunkLib.inf
new file mode 100644
index 0000000..8f760df
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib/ThunkLib.inf
@@ -0,0 +1,67 @@
+## @file
+# @todo ADD DESCRIPTION
+#
+#@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 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
+#
+
+[defines]
+BASE_NAME = ThunkLib
+COMPONENT_TYPE = LIBRARY
+
+[sources.common]
+
+[sources.ia32]
+ Ia32/x86Thunk.c
+ Ia32/Thunk16.asm
+
+[sources.x64]
+ x64/x86Thunk.c
+ x64/Thunk16.asm
+ x64/FxSave.asm
+ x64/FxRestore.asm
+
+[includes.common]
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EFI_SOURCE)/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include
+
+#
+# Edk II Glue Library, some hearder are included by R9 header so have to include
+#
+
+ $(EFI_SOURCE)
+ $(EFI_SOURCE)/Framework
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+
+[libraries.common]
+
+[nmake.common]
+ C_FLAGS = $(C_FLAGS)
diff --git a/ReferenceCode/Haswell/Library/ThunkLib/x64/FxRestore.asm b/ReferenceCode/Haswell/Library/ThunkLib/x64/FxRestore.asm
new file mode 100644
index 0000000..54bab05
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib/x64/FxRestore.asm
@@ -0,0 +1,45 @@
+;/*++
+; 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) 2006 - 2010 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:
+;
+; FxRestore.Asm
+;
+; Abstract:
+;
+; AsmFxRestore function
+;
+; Notes:
+;
+;------------------------------------------------------------------------------
+
+ .code
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; AsmFxRestore (
+; IN CONST IA32_FX_BUFFER *Buffer
+; );
+;------------------------------------------------------------------------------
+AsmFxRestore PROC
+ fxrstor [rcx]
+ ret
+AsmFxRestore ENDP
+
+ END
diff --git a/ReferenceCode/Haswell/Library/ThunkLib/x64/FxSave.asm b/ReferenceCode/Haswell/Library/ThunkLib/x64/FxSave.asm
new file mode 100644
index 0000000..c95ba0b
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib/x64/FxSave.asm
@@ -0,0 +1,45 @@
+;/*++
+; 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) 2006 - 2010 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:
+;
+; FxSave.Asm
+;
+; Abstract:
+;
+; AsmFxSave function
+;
+; Notes:
+;
+;------------------------------------------------------------------------------
+
+ .code
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; AsmFxSave (
+; OUT IA32_FX_BUFFER *Buffer
+; );
+;------------------------------------------------------------------------------
+AsmFxSave PROC
+ fxsave [rcx]
+ ret
+AsmFxSave ENDP
+
+ END
diff --git a/ReferenceCode/Haswell/Library/ThunkLib/x64/Thunk16.asm b/ReferenceCode/Haswell/Library/ThunkLib/x64/Thunk16.asm
new file mode 100644
index 0000000..89bb447
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib/x64/Thunk16.asm
@@ -0,0 +1,216 @@
+;/*++
+; 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) 2006 - 2010 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:
+;
+; Thunk.asm
+;
+; Abstract:
+;
+; Real mode thunk
+;
+;------------------------------------------------------------------------------
+
+EXTERNDEF mCode16Size:QWORD
+
+ .const
+
+mCode16Size DQ _Code16End - _Code16Addr
+
+ .data
+
+NullSegSel DQ 0
+_16CsSegSel LABEL QWORD
+ DW -1
+ DW 0
+ DB 0
+ DB 9bh
+ DB 8fh ; 16-bit segment
+ DB 0
+
+_16Gdtr LABEL FWORD
+ DW $ - offset NullSegSel - 1
+ DQ offset NullSegSel
+
+ .code
+
+IA32_REGS STRUC 4t
+_EDI DD ?
+_ESI DD ?
+_EBP DD ?
+_ESP DD ?
+_EBX DD ?
+_EDX DD ?
+_ECX DD ?
+_EAX DD ?
+_DS DW ?
+_ES DW ?
+_FS DW ?
+_GS DW ?
+_RFLAGS DQ ?
+_EIP DD ?
+_CS DW ?
+_SS DW ?
+IA32_REGS ENDS
+
+_STK16 STRUC 1t
+RetEip DD ?
+RetCs DW ?
+ThunkFlags DW ?
+SavedGdtr FWORD ?
+Resvd1 DW ?
+SavedCr0 DD ?
+SavedCr4 DD ?
+_STK16 ENDS
+
+_Thunk16 PROC USES rbp rbx rsi rdi r12 r13 r14 r15
+
+ push fs
+ push gs
+
+ mov r12d, ds
+ mov r13d, es
+ mov r14d, ss
+ mov r15, rsp
+ mov rsi, rcx
+ movzx r10, (IA32_REGS ptr [rsi])._SS
+ xor rdi, rdi
+ mov edi, (IA32_REGS ptr [rsi])._ESP
+ add rdi, - sizeof (IA32_REGS) - sizeof (_STK16)
+ push rdi
+ imul rax, r10, 16
+ add rdi, rax
+ push sizeof (IA32_REGS) / 4
+ pop rcx
+ rep movsd
+ pop rbx ; rbx <- 16-bit stack offset
+ lea eax, @F ; return offset
+ stosd
+ mov eax, cs ; return segment
+ stosw
+ mov eax, edx ; THUNK Flags
+ stosw
+ sgdt fword ptr [rsp + 58h] ; save GDTR
+ mov rax, [rsp + 58h]
+ stosq
+ mov rax, cr0 ; save CR0
+ mov esi, eax ; esi <- CR0 to set
+ stosd
+ mov rax, cr4 ; save CR4
+ stosd
+ sidt fword ptr [rsp + 58h] ; save IDTR
+ and esi, 07ffffffeh ;NOT 080000001h ; clear PE & PG bits
+ mov rdi, r10 ; rdi <- 16-bit stack segment
+
+ shl r8, 16
+ push r8 ; far jmp address
+ lea eax, @16Bit
+ push rax
+ mov word ptr [rsp + 4], 8
+ lgdt _16Gdtr
+ retf
+@16Bit:
+ mov cr0, rsi ; disable PE & PG
+ DB 66h
+ mov ecx, 0c0000080h
+ rdmsr
+ and ah, NOT 1
+ wrmsr ; clear LME bit
+ mov rax, cr4
+ and al, NOT 30h ; clear PAE & PSE
+ mov cr4, rax
+ retf
+@@:
+ xor rax, rax
+ mov eax, ss
+ shl eax, 4
+ add eax, esp ; rax <- address of 16-bit stack
+ mov rsp, r15
+ lidt fword ptr [rsp + 58h] ; restore IDTR
+ mov ds, r12d
+ mov es, r13d
+ mov ss, r14d
+ pop gs
+ pop fs
+ ret
+_Thunk16 ENDP
+
+ ALIGN 10h
+
+_Code16Addr PROC
+_Code16Addr ENDP
+
+RealMode PROC
+ mov ss, edi
+ mov sp, bx ; set up 16-bit stack
+ DB 2eh, 0fh, 1, 1eh
+ DW _16Idtr - _Code16Addr ; lidt _16Idtr
+ DB 66h, 61h ; popad
+ DB 1fh ; pop ds
+ DB 7 ; pop es
+ pop fs
+ pop gs
+
+ add esp, 8 ; skip RFLAGS
+ DB 67h, 0f7h, 44h, 24h, 0eh, 1, 0 ; test [esp + 0eh], 1
+ jz @F
+ pushfq ; pushf, actually
+@@:
+ DB 0eh ; push cs
+ DB 68h ; push /iw
+ DW @FarCallRet - _Code16Addr
+ jz @F
+ DB 66h
+ jmp fword ptr [esp + 6]
+@@:
+ DB 66h
+ jmp fword ptr [esp + 4]
+@FarCallRet:
+ DB 66h
+ push 0 ; push a dword of zero
+ pushf ; pushfd, actually
+ push gs
+ push fs
+ DB 6 ; push es
+ DB 1eh ; push ds
+ DB 66h, 60h ; pushad
+ cli
+
+ DB 66h
+ lgdt (_STK16 ptr [esp + sizeof(IA32_REGS)]).SavedGdtr
+ DB 66h
+ mov eax, (_STK16 ptr [esp + sizeof(IA32_REGS)]).SavedCr4
+ mov cr4, rax
+ DB 66h
+ mov ecx, 0c0000080h
+ rdmsr
+ or ah, 1
+ wrmsr ; set LME
+ DB 66h
+ mov eax, (_STK16 ptr [esp + sizeof(IA32_REGS)]).SavedCr0
+ mov cr0, rax
+ DB 66h
+ jmp fword ptr (_STK16 ptr [esp + sizeof(IA32_REGS)]).RetEip
+
+RealMode ENDP
+
+_16Idtr FWORD (1 SHL 10) - 1
+
+_Code16End:
+
+ END
diff --git a/ReferenceCode/Haswell/Library/ThunkLib/x64/ThunkLibx64.cif b/ReferenceCode/Haswell/Library/ThunkLib/x64/ThunkLibx64.cif
new file mode 100644
index 0000000..aa6ac0f
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib/x64/ThunkLibx64.cif
@@ -0,0 +1,11 @@
+<component>
+ name = "ThunkLib x64"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\Library\ThunkLib\x64"
+ RefName = "ThunkLibx64"
+[files]
+"x86Thunk.c"
+"Thunk16.asm"
+"FxSave.asm"
+"FxRestore.asm"
+<endComponent>
diff --git a/ReferenceCode/Haswell/Library/ThunkLib/x64/x86Thunk.c b/ReferenceCode/Haswell/Library/ThunkLib/x64/x86Thunk.c
new file mode 100644
index 0000000..dadb37e
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/ThunkLib/x64/x86Thunk.c
@@ -0,0 +1,272 @@
+/** @file
+ Real Mode Thunk Functions for IA32 and X64
+
+@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 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
+
+**/
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "ThunkLib.h"
+#define _THUNK_INTERRUPT 0x10000
+#endif
+
+extern const UINTN mCode16Size;
+
+extern
+IA32_REGISTER_SET *
+EFIAPI
+_Thunk16 (
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 ThunkFlags,
+ IN UINT32 RealModeCs
+ );
+
+extern
+VOID
+EFIAPI
+_Code16Addr (
+ VOID
+ );
+
+extern
+void
+EFIAPI
+AsmFxRestore (
+ IN CONST IA32_FX_BUFFER *Buffer
+ );
+
+extern
+void
+EFIAPI
+AsmFxSave (
+ OUT IA32_FX_BUFFER *Buffer
+ );
+
+/**
+ Returns the properties of this real mode thunk implementation. Currently
+ there are 2 properties has been defined, the minimum real mode buffer size
+ and the minimum stack size.
+
+ @param[in] MinimumStackSize - The minimum size required for a 16-bit stack.
+
+ @retval The minimum size of the real mode buffer needed by this thunk implementation
+ @retval is returned.
+**/
+UINTN
+EFIAPI
+R8AsmThunk16GetProperties (
+ OUT UINTN *MinimumStackSize
+ )
+{
+ ///
+ /// This size should be large enough to hold the register set as well as saved
+ /// CPU contexts including GDTR, CR0 and CR4
+ ///
+ if (MinimumStackSize) {
+ *MinimumStackSize = sizeof (IA32_REGISTER_SET) + 0x200;
+ }
+
+ return mCode16Size;
+}
+
+/**
+ Tell this real mode thunk implementation the address and size of the real
+ mode buffer needed.
+
+ @param[in] ThunkContext - The thunk context whose properties to set.
+ @param[in] RealModeBuffer - The address of the buffer allocated by caller. It should be
+ aligned on a 16-byte boundary.
+ This buffer must be in identity mapped pages.
+ @param[in] BufferSize - The size of RealModeBuffer. Must be larger than the minimum
+ size required as returned by R8AsmThunk16GetProperties().
+**/
+THUNK16_CONTEXT *
+EFIAPI
+R8AsmThunk16SetProperties (
+ OUT THUNK16_CONTEXT *ThunkContext,
+ IN VOID *RealModeBuffer,
+ IN UINTN BufferSize
+ )
+{
+ BufferSize &= ~3;
+
+ ASSERT ((UINTN) RealModeBuffer < 0x100000);
+ ASSERT (((UINTN) RealModeBuffer & 0xf) == 0);
+ ASSERT (BufferSize >= mCode16Size);
+
+ ThunkContext->RealModeBuffer = (UINT32) (UINTN) RealModeBuffer;
+ ThunkContext->DefaultStack = (UINT32) (ThunkContext->RealModeBuffer + BufferSize);
+ CopyMem (RealModeBuffer, (VOID *) (UINTN) _Code16Addr, mCode16Size);
+ return ThunkContext;
+}
+
+/**
+ Reset all internal states to their initial values. The caller should not
+ release the real mode buffer until after a call to this function.
+
+ @param[in] ThunkContext - The thunk context to destroy.
+**/
+VOID
+EFIAPI
+R8AsmThunk16Destroy (
+ IN OUT THUNK16_CONTEXT *ThunkContext
+ )
+{
+ ThunkContext->RealModeBuffer = 0;
+}
+
+/**
+ Do the 16-bit thunk code.
+
+ NOTE: This function must be called on TPL_HIGH_LEVEL or with interrupts
+ disabled because of GDTR and IDTR manipulations.
+ This function must be placed in identity mapped pages.
+
+ @param[in] ThunkContext - Thunk context to use.
+ @param[in] RegisterSet - CPU registers would be set to the values contained in this
+ structure before making the far call. Then CPU registers are
+ copied back to this structure.
+ SS:ESP points to the real mode stack if THUNK_USER_STACK is
+ set on input, otherwise ignored.
+ EFlages is ignored on input.
+ On output, values of CS, EIP, SS and ESP should be ignored.
+ @param[in] ThunkFlags - 2 flags have currently been defined, THUNK_SAVE_FP_STATE and
+ THUNK_USER_STACK.
+ THUNK_SAVE_FP_STATE - FPU state would be saved/restored
+ before/after calling real mode code.
+ THUNK_USER_STACK - The stack specified by SS:ESP would be
+ used instead of the default stack.
+
+ @retval RegisterSet is returned.
+**/
+static
+IA32_REGISTER_SET *
+EFIAPI
+R8AsmThunk16 (
+ IN THUNK16_CONTEXT *ThunkContext,
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 ThunkFlags
+ )
+{
+ IA32_FX_BUFFER *FpSavedState;
+ UINT8 FpBuffer[sizeof (*FpSavedState) + 0x10];
+
+ ASSERT (ThunkContext->RealModeBuffer != 0);
+ ASSERT ((ThunkContext->RealModeBuffer & 0xf) == 0);
+
+ FpSavedState = (IA32_FX_BUFFER *) (((UINTN) FpBuffer + 0xf) &~0xf);
+
+ if (!(ThunkFlags & THUNK_USER_STACK)) {
+ RegisterSet->E.ESP = (UINT16) ThunkContext->DefaultStack;
+ RegisterSet->E.SS = (UINT16) ((ThunkContext->DefaultStack >> 4) & 0xf000);
+ }
+
+ if (ThunkFlags & THUNK_SAVE_FP_STATE) {
+ AsmFxSave (FpSavedState);
+ }
+
+ ASSERT ((RegisterSet->E.ESP >> 16) == 0);
+
+ CopyMem (
+ RegisterSet,
+ _Thunk16 (RegisterSet,
+ (UINT16) (ThunkFlags >> 16),
+ ThunkContext->RealModeBuffer >> 4),
+ sizeof (*RegisterSet)
+ );
+
+ if (ThunkFlags & THUNK_SAVE_FP_STATE) {
+ AsmFxRestore (FpSavedState);
+ }
+
+ return RegisterSet;
+}
+
+/**
+ Make a far call to 16-bit code.
+
+ NOTE: This function must be called on TPL_HIGH_LEVEL or with interrupts
+ disabled because of GDTR and IDTR manipulations.
+ This function must be placed in identity mapped pages.
+
+ @param[in] ThunkContext - Thunk context to use.
+ @param[in] RegisterSet - CPU registers would be set to the values contained in this
+ structure before making the far call. Then CPU registers are
+ copied back to this structure.
+ CS:EIP points to the real mode code being called on input.
+ SS:ESP points to the real mode stack if THUNK_USER_STACK is
+ set on input, otherwise ignored.
+ EFlages is ignored on input.
+ On output, values of CS, EIP, SS and ESP should be ignored.
+ @param[in] Flags - 2 flags have currently been defined, THUNK_SAVE_FP_STATE and
+ THUNK_USER_STACK.
+ THUNK_SAVE_FP_STATE - FPU state would be saved/restored
+ before/after calling real mode code.
+ THUNK_USER_STACK - The stack specified by SS:ESP would be
+ used instead of the default stack.
+
+ @retval RegisterSet is returned.
+**/
+IA32_REGISTER_SET *
+EFIAPI
+R8AsmThunk16FarCall86 (
+ IN THUNK16_CONTEXT *ThunkContext,
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 Flags
+ )
+{
+ return R8AsmThunk16 (ThunkContext, RegisterSet, Flags);
+}
+
+/**
+ Invoke a 16-bit interrupt handler.
+
+ NOTE: This function must be called on TPL_HIGH_LEVEL or with interrupts
+ disabled because of GDTR and IDTR manipulations.
+ This function must be placed in identity mapped pages.
+
+ @param[in] ThunkContext - Thunk context to use.
+ @param[in] IntNumber - The ordinal of the interrupt handler ranging from 0 to 255.
+ @param[in] RegisterSet - CPU registers would be set to the values contained in this
+ structure before making the far call. Then CPU registers are
+ copied back to this structure.
+ SS:ESP points to the real mode stack if THUNK_USER_STACK is
+ set on input, otherwise ignored.
+ EFlages is ignored on input.
+ On output, values of CS, EIP, SS and ESP should be ignored.
+ @param[in] Flags - 2 flags have currently been defined, THUNK_SAVE_FP_STATE and
+ THUNK_USER_STACK.
+ THUNK_SAVE_FP_STATE - FPU state would be saved/restored
+ before/after calling real mode code.
+ THUNK_USER_STACK - The stack specified by SS:ESP would be
+ used instead of the default stack.
+
+ @retval RegisterSet is returned.
+**/
+IA32_REGISTER_SET *
+EFIAPI
+R8AsmThunk16Int86 (
+ IN THUNK16_CONTEXT *ThunkContext,
+ IN UINT8 IntNumber,
+ IN OUT IA32_REGISTER_SET *RegisterSet,
+ IN UINT32 Flags
+ )
+{
+ RegisterSet->E.Eip = (UINT16) ((UINT32 *) NULL)[IntNumber];
+ RegisterSet->E.CS = (UINT16) (((UINT32 *) NULL)[IntNumber] >> 16);
+ return R8AsmThunk16 (ThunkContext, RegisterSet, Flags | _THUNK_INTERRUPT);
+}
diff --git a/ReferenceCode/Haswell/Library/TxtLib.cif b/ReferenceCode/Haswell/Library/TxtLib.cif
new file mode 100644
index 0000000..3d672e9
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/TxtLib.cif
@@ -0,0 +1,11 @@
+<component>
+ name = "TxtLib"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\Library\"
+ RefName = "TxtLib"
+[files]
+"TxtLib.sdl"
+"TxtLib.mak"
+"TxtLib\TxtLib.inf"
+"TxtLib\Ia32\TxtPeiLib.asm"
+<endComponent>
diff --git a/ReferenceCode/Haswell/Library/TxtLib.mak b/ReferenceCode/Haswell/Library/TxtLib.mak
new file mode 100644
index 0000000..f933155
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/TxtLib.mak
@@ -0,0 +1,16 @@
+# MAK file for the ModulePart:CpuPlatformLib
+
+$(TxtLib_LIB) : TxtLib
+
+TxtLib : $(BUILD_DIR)\TxtLib.mak TxtLibBin
+
+$(BUILD_DIR)\TxtLib.mak : $(TxtLib_DIR)\$(@B).cif $(TxtLib_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(TxtLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+TxtLibBin :
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\TxtLib.mak all\
+ BUILD_DIR=$(BUILD_DIR)\IA32 \
+ "AFLAGS=$(AFLAGS) $(PROJECT_CPU_INCLUDES)" \
+ "MY_INCLUDES=$(EDK_INCLUDES) $(EdkIIGlueLib_INCLUDES) $(PROJECT_CPU_INCLUDES) $(INTEL_PCH_INCLUDES)" \
+ TYPE=PEI_LIBRARY "PARAMETERS=LIBRARY_NAME=$$(TxtLib_LIB)"
diff --git a/ReferenceCode/Haswell/Library/TxtLib.sdl b/ReferenceCode/Haswell/Library/TxtLib.sdl
new file mode 100644
index 0000000..028362b
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/TxtLib.sdl
@@ -0,0 +1,32 @@
+TOKEN
+ Name = TxtLib_SUPPORT
+ Value = "1"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+ Help = "Main switch to enable TxtLib support in Project"
+End
+
+TOKEN
+ Name = "TxtLib_LIB"
+ Value = "$$(LIB_BUILD_DIR)\TxtLib.lib"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+PATH
+ Name = "TxtLib_DIR"
+End
+
+ELINK
+ Name = "/I$(TxtLib_DIR)\TxtLib"
+ Parent = "PROJECT_CPU_INCLUDES"
+ InvokeOrder = AfterParent
+End
+
+MODULE
+ Help = "Includes TxtLib.mak to Project"
+ File = "TxtLib.mak"
+End
+
diff --git a/ReferenceCode/Haswell/Library/TxtLib/Ia32/TxtPeiLib.asm b/ReferenceCode/Haswell/Library/TxtLib/Ia32/TxtPeiLib.asm
new file mode 100644
index 0000000..34fcd35
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/TxtLib/Ia32/TxtPeiLib.asm
@@ -0,0 +1,99 @@
+;/*++
+; 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
+;--*/
+;
+;/*++
+;
+; Copyright (c) 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.
+;
+;
+; Module Name:
+;
+; TxtPeiLib.asm
+;
+; Abstract:
+;
+; This file contains the code to determine Processor/Chipset TXT capaiblity
+;
+;--*/
+
+ .XLIST
+ include txt.inc
+ .LIST
+
+ .686P
+ .MMX
+ .XMM
+ .MODEL FLAT,C
+ .CODE
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: CheckSmxCapabilities
+;
+; Input: None
+;
+; Output: None
+;
+; Registers: None are preserved
+;
+; Description: Execute GETSEC[CAPABILITIES] to report the SMX capabilities
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+
+CheckSmxCapabilities PROC PUBLIC USES ebx
+
+ ;
+ ; Check whether SMX is supported
+ ;
+ mov eax, 1
+ cpuid
+ bt ecx, IA32_CPUID_SMX_B
+
+ .IF !CARRY?
+ mov eax, 0
+ jmp @F
+ .ENDIF
+
+ ;
+ ; Save cr4
+ ;
+ mov edx, CR4
+
+ ;
+ ; Enable SMXE
+ ;
+ mov eax, CR4
+ or eax, CR4_SMXE
+ mov CR4, eax
+
+ ;
+ ; Call GETSEC[CAPABILITIES]
+ ;
+ mov eax, CAPABILITIES ; eax = CAPABILITIES
+ mov ebx, 0
+ _GETSEC
+
+ ;
+ ; Restore cr4
+ ;
+ mov CR4, edx
+
+@@:
+ ret
+CheckSmxCapabilities ENDP
+
+END
diff --git a/ReferenceCode/Haswell/Library/TxtLib/TxtLib.inf b/ReferenceCode/Haswell/Library/TxtLib/TxtLib.inf
new file mode 100644
index 0000000..46ae16b
--- /dev/null
+++ b/ReferenceCode/Haswell/Library/TxtLib/TxtLib.inf
@@ -0,0 +1,60 @@
+## @file
+# Component description file for TXT Lib
+#
+#@copyright
+# Copyright (c) 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
+#
+
+[defines]
+BASE_NAME = TxtLib
+COMPONENT_TYPE = LIBRARY
+
+[sources.common]
+ Ia32/TxtPeiLib.asm
+
+[sources.ia32]
+
+[sources.x64]
+
+[sources.ipf]
+
+[includes.common]
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include/Library
+
+#
+# EDK II Glue Library utilizes some standard headers from EDK
+#
+ $(EFI_SOURCE)
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+
+[libraries.common]
+
+[nmake.common]
diff --git a/ReferenceCode/Haswell/PowerManagement/AcpiTables/PowerMgmtAcpiTables.cif b/ReferenceCode/Haswell/PowerManagement/AcpiTables/PowerMgmtAcpiTables.cif
new file mode 100644
index 0000000..20c2418
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/AcpiTables/PowerMgmtAcpiTables.cif
@@ -0,0 +1,19 @@
+<component>
+ name = "PowerManagementAcpiTables"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\PowerManagement\AcpiTables\"
+ RefName = "PowerManagementAcpiTables"
+[files]
+"PowerMgmtAcpiTables.sdl"
+"PowerMgmtAcpiTables.mak"
+"PowerMgmtAcpiTables.inf"
+"Ssdt\ApCst.asl"
+"Ssdt\ApIst.asl"
+"Ssdt\ApTst.asl"
+"Ssdt\Cpu0Cst.asl"
+"Ssdt\Cpu0Ist.asl"
+"Ssdt\Cpu0Tst.asl"
+"Ssdt\CpuPm.asl"
+"Ssdt\LakeTiny.asl"
+"Ssdt\Ctdp.asl"
+<endComponent>
diff --git a/ReferenceCode/Haswell/PowerManagement/AcpiTables/PowerMgmtAcpiTables.inf b/ReferenceCode/Haswell/PowerManagement/AcpiTables/PowerMgmtAcpiTables.inf
new file mode 100644
index 0000000..511a086
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/AcpiTables/PowerMgmtAcpiTables.inf
@@ -0,0 +1,77 @@
+## @file
+# Component description file for the ACPI tables
+#
+#@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 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
+#
+
+
+[defines]
+BASE_NAME = PowerManagementAcpiTables2
+FILE_GUID = 299141BB-211A-48a5-92C0-6F9A0A3A006E
+COMPONENT_TYPE = ACPITABLE
+FFS_EXT = .ffs
+
+[sources.common]
+ Ssdt/Cpu0Cst.asl
+ Ssdt/Cpu0Ist.asl
+ Ssdt/Cpu0Tst.asl
+ Ssdt/ApCst.asl
+ Ssdt/ApIst.asl
+ Ssdt/ApTst.asl
+ Ssdt/CpuPm.asl
+ Ssdt/LakeTiny.asl
+ Ssdt/Ctdp.asl
+
+[libraries.common]
+
+[includes.common]
+ .
+ $(EFI_SOURCE)
+ $(EFI_SOURCE)/Include
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EFI_SOURCE)/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include
+#
+# Typically the sample code referenced will be available in the code base already
+# So keep this include at the end to defer to the source base definition
+# and only use the sample code definition if source base does not include these files.
+#
+# $(EFI_SOURCE)/$(PROJECT_PPM_ROOT)/SampleCode/Include
+
+#
+# Edk II Glue Library, some hearder are included by R9 header so have to include
+#
+
+ $(EFI_SOURCE)
+ $(EFI_SOURCE)/Framework
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+
+[nmake.common]
diff --git a/ReferenceCode/Haswell/PowerManagement/AcpiTables/PowerMgmtAcpiTables.mak b/ReferenceCode/Haswell/PowerManagement/AcpiTables/PowerMgmtAcpiTables.mak
new file mode 100644
index 0000000..1f737f3
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/AcpiTables/PowerMgmtAcpiTables.mak
@@ -0,0 +1,168 @@
+# /*++
+# Copyright (c) 2009 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.
+# --*/
+# MAK file for the ModulePart:PowerManagementAcpiTables
+
+#-----------------------------------------------------------------------
+# ASL compiler definition
+#-----------------------------------------------------------------------
+MASL = $(SILENT)asl.exe # Microsoft ASL compiler
+!IF "$(ACPIPLATFORM_ASL_COMPILER)"==""
+!ERROR It is an invalid path, please check your ASL compiler path.
+!ENDIF
+
+IASL = $(ACPIPLATFORM_ASL_COMPILER)
+#-----------------------------------------------------------------------
+ASL_COMPILER = IASL # Default ASL compiler. Can be 'IASL' for Intel ASL and 'MASL' for Microsoft ASL compiler.
+# Note. Msft. ASL compiler of version 1.0.14NT correctly process ACPI 2.0 extended ASL objects.
+#-----------------------------------------------------------------------
+EDK : PPMASL
+
+ALLPPMSEC = $(BUILD_DIR)\CPUPM.sec\
+ $(BUILD_DIR)\CPU0IST.sec\
+ $(BUILD_DIR)\APIST.sec\
+ $(BUILD_DIR)\CPU0TST.sec\
+ $(BUILD_DIR)\APTST.sec\
+ $(BUILD_DIR)\CPU0CST.sec\
+ $(BUILD_DIR)\APCST.sec\
+ $(BUILD_DIR)\LakeTiny.sec\
+ $(BUILD_DIR)\Ctdp.sec
+
+PPMASL: $(BUILD_DIR)\PPMACPI.ffs
+
+$(BUILD_DIR)\CPUPM.aml: $(INTEL_CPUPPM_ASL_FILE)
+!if "$(ASL_COMPILER)" == "MASL"
+ @$(MASL) /Fo=$@ $**
+!elseif "$(ASL_COMPILER)" == "IASL"
+ @cl /C /EP -I $(PROJECT_CPU_INCLUDES) $(INTEL_CPUPPM_ASL_FILE) > $(BUILD_DIR)\CpuPm.asl
+ $(IASL) -p $(BUILD_DIR)\CPUPM.aml $(BUILD_DIR)\CpuPm.asl
+!endif
+
+$(BUILD_DIR)\CPU0IST.aml: $(INTEL_CPU0IST_ASL_FILE)
+!if "$(ASL_COMPILER)" == "MASL"
+ $(MASL) /Fo=$@ $**
+!elseif "$(ASL_COMPILER)" == "IASL"
+ @cl /C /EP -I $(PROJECT_CPU_INCLUDES) $(INTEL_CPU0IST_ASL_FILE) > $(BUILD_DIR)\Cpu0Ist.asl
+ $(IASL) -p $(BUILD_DIR)\CPU0IST.aml $(BUILD_DIR)\Cpu0Ist.asl
+!endif
+
+$(BUILD_DIR)\APIST.aml: $(INTEL_APIST_ASL_FILE)
+!if "$(ASL_COMPILER)" == "MASL"
+ $(MASL) /Fo=$@ $**
+!elseif "$(ASL_COMPILER)" == "IASL"
+ $(IASL) -p $(BUILD_DIR)\APIST.aml $(INTEL_APIST_ASL_FILE)
+!endif
+
+$(BUILD_DIR)\CPU0CST.aml: $(INTEL_CPU0CST_ASL_FILE)
+!if "$(ASL_COMPILER)" == "MASL"
+ $(MASL) /Fo=$@ $**
+!elseif "$(ASL_COMPILER)" == "IASL"
+ @cl /C /EP $(PROJECT_CPU_INCLUDES) $(INTEL_CPU0CST_ASL_FILE) > $(BUILD_DIR)\Cpu0Cst.asl
+ $(IASL) -p $(BUILD_DIR)\CPU0CST.aml $(BUILD_DIR)\Cpu0Cst.asl
+!endif
+
+$(BUILD_DIR)\CPU0TST.aml: $(INTEL_CPU0TST_ASL_FILE)
+!if "$(ASL_COMPILER)" == "MASL"
+ $(MASL) /Fo=$@ $**
+!elseif "$(ASL_COMPILER)" == "IASL"
+ @cl /C /EP $(PROJECT_CPU_INCLUDES) $(INTEL_CPU0TST_ASL_FILE) > $(BUILD_DIR)\Cpu0Tst.asl
+ $(IASL) -p $(BUILD_DIR)\CPU0TST.aml $(BUILD_DIR)\Cpu0Tst.asl
+!endif
+
+$(BUILD_DIR)\APCST.aml: $(INTEL_APCST_ASL_FILE)
+!if "$(ASL_COMPILER)" == "MASL"
+ $(MASL) /Fo=$@ $**
+!elseif "$(ASL_COMPILER)" == "IASL"
+ $(IASL) -p $(BUILD_DIR)\APCST.aml $(INTEL_APCST_ASL_FILE)
+!endif
+
+$(BUILD_DIR)\CPU0TST.aml: $(INTEL_CPU0TST_ASL_FILE)
+!if "$(ASL_COMPILER)" == "MASL"
+ $(MASL) /Fo=$@ $**
+!elseif "$(ASL_COMPILER)" == "IASL"
+ $(IASL) -p $(BUILD_DIR)\CPU0TST.aml $(INTEL_CPU0TST_ASL_FILE)
+!endif
+
+$(BUILD_DIR)\APTST.aml: $(INTEL_APTST_ASL_FILE)
+!if "$(ASL_COMPILER)" == "MASL"
+ $(MASL) /Fo=$@ $**
+!elseif "$(ASL_COMPILER)" == "IASL"
+ $(IASL) -p $(BUILD_DIR)\ApTst.aml $(INTEL_APTST_ASL_FILE)
+!endif
+
+$(BUILD_DIR)\LakeTiny.aml: $(INTEL_LAKETINY_ASL_FILE)
+!if "$(ASL_COMPILER)" == "MASL"
+ $(MASL) /Fo=$@ $**
+!elseif "$(ASL_COMPILER)" == "IASL"
+ $(IASL) -p $(BUILD_DIR)\LakeTiny.aml $(INTEL_LAKETINY_ASL_FILE)
+!endif
+
+$(BUILD_DIR)\Ctdp.aml: $(INTEL_CTDP_ASL_FILE)
+!if "$(ASL_COMPILER)" == "MASL"
+ $(MASL) /Fo=$@ $**
+!elseif "$(ASL_COMPILER)" == "IASL"
+ $(IASL) -p $(BUILD_DIR)\Ctdp.aml $(INTEL_CTDP_ASL_FILE)
+!endif
+
+$(BUILD_DIR)\CPUPM.sec: $(BUILD_DIR)\CPUPM.aml
+ $(GENSECTION) -I $** -O $@ -S EFI_SECTION_RAW
+
+$(BUILD_DIR)\CPU0IST.sec: $(BUILD_DIR)\CPU0IST.aml
+ $(GENSECTION) -I $** -O $@ -S EFI_SECTION_RAW
+
+$(BUILD_DIR)\APIST.sec: $(BUILD_DIR)\APIST.aml
+ $(GENSECTION) -I $** -O $@ -S EFI_SECTION_RAW
+
+$(BUILD_DIR)\CPU0TST.sec: $(BUILD_DIR)\CPU0TST.aml
+ $(GENSECTION) -I $** -O $@ -S EFI_SECTION_RAW
+
+$(BUILD_DIR)\APTST.sec: $(BUILD_DIR)\APTST.aml
+ $(GENSECTION) -I $** -O $@ -S EFI_SECTION_RAW
+
+$(BUILD_DIR)\CPU0CST.sec: $(BUILD_DIR)\CPU0CST.aml
+ $(GENSECTION) -I $** -O $@ -S EFI_SECTION_RAW
+
+$(BUILD_DIR)\APCST.sec: $(BUILD_DIR)\APCST.aml
+ $(GENSECTION) -I $** -O $@ -S EFI_SECTION_RAW
+
+$(BUILD_DIR)\LakeTiny.sec: $(BUILD_DIR)\LakeTiny.aml
+ $(GENSECTION) -I $** -O $@ -S EFI_SECTION_RAW
+
+$(BUILD_DIR)\Ctdp.sec: $(BUILD_DIR)\Ctdp.aml
+ $(GENSECTION) -I $** -O $@ -S EFI_SECTION_RAW
+
+#.SUFFIXES: .aml
+#{$(BUILD_DIR)}.aml{$(BUILD_DIR)}.sec:
+# $(GENSECTION) -I $< -O $@ -S EFI_SECTION_RAW
+
+$(BUILD_DIR)\PPMACPI.ffs: $(ALLPPMSEC) $(PowerMgmtDxe_DIR)\PowerMgmtDxe.mak
+ $(GENFFSFILE) -B $(BUILD_DIR) -V -o $@ -P1 <<$(BUILD_DIR)\PPMACPI.pkg
+PACKAGE.INF
+[.]
+BASE_NAME = PPMACPI
+FFS_FILEGUID = 299141BB-211A-48a5-92C0-6F9A0A3A006E
+FFS_FILETYPE = EFI_FV_FILETYPE_FREEFORM
+FFS_ATTRIB_CHECKSUM = TRUE
+
+IMAGE_SCRIPT =
+{
+ Compress (dummy) {
+ $(PROJECT_DIR)\$(BUILD_DIR)\CPUPM.sec
+ $(PROJECT_DIR)\$(BUILD_DIR)\CPU0IST.sec
+ $(PROJECT_DIR)\$(BUILD_DIR)\APIST.sec
+ $(PROJECT_DIR)\$(BUILD_DIR)\CPU0TST.sec
+ $(PROJECT_DIR)\$(BUILD_DIR)\APTST.sec
+ $(PROJECT_DIR)\$(BUILD_DIR)\CPU0CST.sec
+ $(PROJECT_DIR)\$(BUILD_DIR)\APCST.sec
+ $(PROJECT_DIR)\$(BUILD_DIR)\LakeTiny.sec
+ $(PROJECT_DIR)\$(BUILD_DIR)\Ctdp.sec
+ }
+}
+<<KEEP
diff --git a/ReferenceCode/Haswell/PowerManagement/AcpiTables/PowerMgmtAcpiTables.sdl b/ReferenceCode/Haswell/PowerManagement/AcpiTables/PowerMgmtAcpiTables.sdl
new file mode 100644
index 0000000..bd2bf63
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/AcpiTables/PowerMgmtAcpiTables.sdl
@@ -0,0 +1,87 @@
+TOKEN
+ Name = PowerManagementAcpiTables_SUPPORT
+ Value = 1
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+ Help = "Main switch to enable PowerManagementAcpiTables support in Project"
+End
+
+MODULE
+ Help = "Includes PowerMgmtAcpiTables.mak to Project"
+ File = "PowerMgmtAcpiTables.mak"
+End
+
+PATH
+ Name = "PPMACPI_DIR"
+End
+
+TOKEN
+ Name = "INTEL_CPUPPM_ASL_FILE"
+ Value = "$(PPMACPI_DIR)\Ssdt\CpuPm.asl"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+TOKEN
+ Name = "INTEL_CPU0IST_ASL_FILE"
+ Value = "$(PPMACPI_DIR)\Ssdt\Cpu0Ist.asl"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+TOKEN
+ Name = "INTEL_APIST_ASL_FILE"
+ Value = "$(PPMACPI_DIR)\Ssdt\ApIst.asl"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+TOKEN
+ Name = "INTEL_CPU0CST_ASL_FILE"
+ Value = "$(PPMACPI_DIR)\Ssdt\Cpu0Cst.asl"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+TOKEN
+ Name = "INTEL_CPU0TST_ASL_FILE"
+ Value = "$(PPMACPI_DIR)\Ssdt\Cpu0Tst.asl"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+TOKEN
+ Name = "INTEL_APCST_ASL_FILE"
+ Value = "$(PPMACPI_DIR)\Ssdt\ApCst.asl"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+TOKEN
+ Name = "INTEL_APTST_ASL_FILE"
+ Value = "$(PPMACPI_DIR)\Ssdt\ApTst.asl"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+TOKEN
+ Name = "INTEL_LAKETINY_ASL_FILE"
+ Value = "$(PPMACPI_DIR)\Ssdt\LakeTiny.asl"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+TOKEN
+ Name = "INTEL_CTDP_ASL_FILE"
+ Value = "$(PPMACPI_DIR)\Ssdt\Ctdp.asl"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\PPMACPI.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End
diff --git a/ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/ApCst.asl b/ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/ApCst.asl
new file mode 100644
index 0000000..3be877d
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/ApCst.asl
@@ -0,0 +1,146 @@
+/*++
+ 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
+--*/
+
+/*++
+
+Copyright (c) 1999 - 2011 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:
+
+ ApCst.asl
+
+Abstract:
+
+ Intel Processor Power Management ACPI Code
+
+ WARNING: You are authorized and licensed to install and use this BIOS code
+ ONLY on an IST PC. This utility may damage any system that does not
+ meet these requirements.
+
+ An IST PC is a computer which
+ (1) Is capable of seamlessly and automatically transitioning among
+ multiple performance states (potentially operating at different
+ efficiency ratings) based upon power source changes, END user
+ preference, processor performance demand, and thermal conditions; and
+ (2) Includes an Intel Pentium II processors, Intel Pentium III
+ processor, Mobile Intel Pentium III Processor-M, Mobile Intel Pentium 4
+ Processor-M, Intel Pentium M Processor, or any other future Intel
+ processors that incorporates the capability to transition between
+ different performance states by altering some, or any combination of,
+ the following processor attributes: core voltage, core frequency, bus
+ frequency, number of processor cores available, or any other attribute
+ that changes the efficiency (instructions/unit time-power) at which the
+ processor operates.
+
+--*/
+
+
+DefinitionBlock (
+ "APCST.aml",
+ "SSDT",
+ 1,
+ "PmRef",
+ "ApCst",
+ 0x3000
+ )
+{
+External(\_PR.CPU1, DeviceObj)
+External(\_PR.CPU2, DeviceObj)
+External(\_PR.CPU3, DeviceObj)
+External(\_PR.CPU4, DeviceObj)
+External(\_PR.CPU5, DeviceObj)
+External(\_PR.CPU6, DeviceObj)
+External(\_PR.CPU7, DeviceObj)
+External(\_PR.CPU0._CST)
+
+ Scope(\_PR.CPU1)
+ {
+ Method(_CST,0)
+ {
+ //
+ // Return P0's _CST object.
+ //
+ Return(\_PR.CPU0._CST)
+ }
+ }
+
+ Scope(\_PR.CPU2)
+ {
+ Method(_CST,0)
+ {
+ //
+ // Return P0's _CST object.
+ //
+ Return(\_PR.CPU0._CST)
+ }
+ }
+
+ Scope(\_PR.CPU3)
+ {
+ Method(_CST,0)
+ {
+ //
+ // Return P0's _CST object.
+ //
+ Return(\_PR.CPU0._CST)
+ }
+ }
+
+ Scope(\_PR.CPU4)
+ {
+ Method(_CST,0)
+ {
+ //
+ // Return P0's _CST object.
+ //
+ Return(\_PR.CPU0._CST)
+ }
+ }
+
+ Scope(\_PR.CPU5)
+ {
+ Method(_CST,0)
+ {
+ //
+ // Return P0's _CST object.
+ //
+ Return(\_PR.CPU0._CST)
+ }
+ }
+
+ Scope(\_PR.CPU6)
+ {
+ Method(_CST,0)
+ {
+ //
+ // Return P0's _CST object.
+ //
+ Return(\_PR.CPU0._CST)
+ }
+ }
+
+ Scope(\_PR.CPU7)
+ {
+ Method(_CST,0)
+ {
+ //
+ // Return P0's _CST object.
+ //
+ Return(\_PR.CPU0._CST)
+ }
+ }
+
+} // End of Definition Block
diff --git a/ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/ApIst.asl b/ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/ApIst.asl
new file mode 100644
index 0000000..612101c
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/ApIst.asl
@@ -0,0 +1,408 @@
+/*++
+ 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
+--*/
+
+/*++
+
+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.
+
+Module Name:
+
+ ApIst.asl
+
+Abstract:
+
+ Intel Processor Power Management ACPI Code
+
+ WARNING: You are authorized and licensed to install and use this BIOS code
+ ONLY on an IST PC. This utility may damage any system that does not
+ meet these requirements.
+
+ An IST PC is a computer which
+ (1) Is capable of seamlessly and automatically transitioning among
+ multiple performance states (potentially operating at different
+ efficiency ratings) based upon power source changes, END user
+ preference, processor performance demand, and thermal conditions; and
+ (2) Includes an Intel Pentium II processors, Intel Pentium III
+ processor, Mobile Intel Pentium III Processor-M, Mobile Intel Pentium 4
+ Processor-M, Intel Pentium M Processor, or any other future Intel
+ processors that incorporates the capability to transition between
+ different performance states by altering some, or any combination of,
+ the following processor attributes: core voltage, core frequency, bus
+ frequency, number of processor cores available, or any other attribute
+ that changes the efficiency (instructions/unit time-power) at which the
+ processor operates.
+
+--*/
+
+
+DefinitionBlock (
+ "APIST.aml",
+ "SSDT",
+ 1,
+ "PmRef",
+ "ApIst",
+ 0x3000
+ )
+{
+ External(\_PR.CPU0._PSS, MethodObj)
+ External(\_PR.CPU0._PCT, MethodObj)
+ External(\_PR.CPU0._PPC, IntObj)
+ External(\_PR.CPU0._PSD, MethodObj)
+ External(\_PR.CPU1, DeviceObj)
+ External(\_PR.CPU2, DeviceObj)
+ External(\_PR.CPU3, DeviceObj)
+ External(\_PR.CPU4, DeviceObj)
+ External(\_PR.CPU5, DeviceObj)
+ External(\_PR.CPU6, DeviceObj)
+ External(\_PR.CPU7, DeviceObj)
+ External (CFGD)
+ External (PDC0)
+ External (MPMF)
+ External (TCNT)
+
+ Scope(\_PR.CPU1)
+ {
+ Method(_PPC,0)
+ {
+ Return(\_PR.CPU0._PPC) // Return P0 _PPC value.
+ }
+
+ Method(_PCT,0)
+ {
+ Return(\_PR.CPU0._PCT) // Return P0 _PCT.
+
+ }
+
+ Method(_PSS,0)
+ {
+ //Return the same table as CPU0 for CMP cases.
+ Return(\_PR.CPU0._PSS)
+ }
+
+ Name (PSDF, 0)
+ //
+ // The _PSD object provides information to the OSPM related
+ // to P-State coordination between processors in a multi-processor
+ // configurations.
+ //
+ Method(_PSD,0)
+ {
+ If ( LNot(PSDF) )
+ {
+ Store (TCNT, Index(DerefOf(Index(HPSD, 0)),4))
+ Store (TCNT, Index(DerefOf(Index(SPSD, 0)),4))
+ Store (Ones, PSDF)
+ }
+ If(And(PDC0,0x0800))
+ {
+ Return(HPSD)
+ }
+ Return(SPSD)
+ }
+ Name(HPSD,Package() // HW_ALL
+ {
+ Package(){5, 0, 0, 0xFE, 0x80}
+ })
+ Name(SPSD,Package() // SW_ALL
+ {
+ Package(){5, 0, 0, 0xFC, 0x80}
+ })
+ }
+
+ Scope(\_PR.CPU2)
+ {
+ Method(_PPC,0)
+ {
+ Return(\_PR.CPU0._PPC) // Return CPU0 _PPC value.
+ }
+
+ Method(_PCT,0)
+ {
+ Return(\_PR.CPU0._PCT) // Return CPU0 _PCT value.
+ }
+
+ Method(_PSS,0)
+ {
+ Return(\_PR.CPU0._PSS) // Return CPU0 _PSS.
+ }
+
+ Name (PSDF, 0)
+ //
+ // The _PSD object provides information to the OSPM related
+ // to P-State coordination between processors in a multi-processor
+ // configurations.
+ //
+ Method(_PSD,0)
+ {
+ If ( LNot(PSDF) )
+ {
+ Store (TCNT, Index(DerefOf(Index(HPSD, 0)),4))
+ Store (TCNT, Index(DerefOf(Index(SPSD, 0)),4))
+ Store (Ones, PSDF)
+ }
+ If(And(PDC0,0x0800))
+ {
+ Return(HPSD)
+ }
+ Return(SPSD)
+ }
+ Name(HPSD,Package() // HW_ALL
+ {
+ Package(){5, 0, 0, 0xFE, 0x80}
+ })
+ Name(SPSD,Package() // SW_ALL
+ {
+ Package(){5, 0, 0, 0xFC, 0x80}
+ })
+ }
+
+
+ Scope(\_PR.CPU3)
+ {
+ Method(_PPC,0)
+ {
+ Return(\_PR.CPU0._PPC) // Return CPU0 _PPC value.
+ }
+
+ Method(_PCT,0)
+ {
+ Return(\_PR.CPU0._PCT) // Return CPU0 _PCT value.
+ }
+
+ Method(_PSS,0)
+ {
+ Return(\_PR.CPU0._PSS) // Return CPU0 _PSS.
+ }
+
+ Name (PSDF, 0)
+ //
+ // The _PSD object provides information to the OSPM related
+ // to P-State coordination between processors in a multi-processor
+ // configurations.
+ //
+ Method(_PSD,0)
+ {
+ If ( LNot(PSDF) )
+ {
+ Store (TCNT, Index(DerefOf(Index(HPSD, 0)),4))
+ Store (TCNT, Index(DerefOf(Index(SPSD, 0)),4))
+ Store (Ones, PSDF)
+ }
+ If(And(PDC0,0x0800))
+ {
+ Return(HPSD)
+ }
+ Return(SPSD)
+ }
+ Name(HPSD,Package() // HW_ALL
+ {
+ Package(){5, 0, 0, 0xFE, 0x80}
+ })
+ Name(SPSD,Package() // SW_ALL
+ {
+ Package(){5, 0, 0, 0xFC, 0x80}
+ })
+ }
+
+ Scope(\_PR.CPU4)
+ {
+ Method(_PPC,0)
+ {
+ Return(\_PR.CPU0._PPC) // Return CPU0 _PPC value.
+ }
+
+ Method(_PCT,0)
+ {
+ Return(\_PR.CPU0._PCT) // Return CPU0 _PCT value.
+ }
+
+ Method(_PSS,0)
+ {
+ Return(\_PR.CPU0._PSS) // Return CPU0 _PSS.
+ }
+
+ Name (PSDF, 0)
+ //
+ // The _PSD object provides information to the OSPM related
+ // to P-State coordination between processors in a multi-processor
+ // configurations.
+ //
+ Method(_PSD,0)
+ {
+ If ( LNot(PSDF) )
+ {
+ Store (TCNT, Index(DerefOf(Index(HPSD, 0)),4))
+ Store (TCNT, Index(DerefOf(Index(SPSD, 0)),4))
+ Store (Ones, PSDF)
+ }
+ If(And(PDC0,0x0800))
+ {
+ Return(HPSD)
+ }
+ Return(SPSD)
+ }
+ Name(HPSD,Package() // HW_ALL
+ {
+ Package(){5, 0, 0, 0xFE, 0x80}
+ })
+ Name(SPSD,Package() // SW_ALL
+ {
+ Package(){5, 0, 0, 0xFC, 0x80}
+ })
+ }
+
+ Scope(\_PR.CPU5)
+ {
+ Method(_PPC,0)
+ {
+ Return(\_PR.CPU0._PPC) // Return CPU0 _PPC value.
+ }
+
+ Method(_PCT,0)
+ {
+ Return(\_PR.CPU0._PCT) // Return CPU0 _PCT value.
+ }
+
+ Method(_PSS,0)
+ {
+ Return(\_PR.CPU0._PSS) // Return CPU0 _PSS.
+ }
+
+ Name (PSDF, 0)
+ //
+ // The _PSD object provides information to the OSPM related
+ // to P-State coordination between processors in a multi-processor
+ // configurations.
+ //
+ Method(_PSD,0)
+ {
+ If ( LNot(PSDF) )
+ {
+ Store (TCNT, Index(DerefOf(Index(HPSD, 0)),4))
+ Store (TCNT, Index(DerefOf(Index(SPSD, 0)),4))
+ Store (Ones, PSDF)
+ }
+ If(And(PDC0,0x0800))
+ {
+ Return(HPSD)
+ }
+ Return(SPSD)
+ }
+ Name(HPSD,Package() // HW_ALL
+ {
+ Package(){5, 0, 0, 0xFE, 0x80}
+ })
+ Name(SPSD,Package() // SW_ALL
+ {
+ Package(){5, 0, 0, 0xFC, 0x80}
+ })
+ }
+
+ Scope(\_PR.CPU6)
+ {
+ Method(_PPC,0)
+ {
+ Return(\_PR.CPU0._PPC) // Return CPU0 _PPC value.
+ }
+
+ Method(_PCT,0)
+ {
+ Return(\_PR.CPU0._PCT) // Return CPU0 _PCT value.
+ }
+
+ Method(_PSS,0)
+ {
+ Return(\_PR.CPU0._PSS) // Return CPU0 _PSS.
+ }
+
+ Name (PSDF, 0)
+ //
+ // The _PSD object provides information to the OSPM related
+ // to P-State coordination between processors in a multi-processor
+ // configurations.
+ //
+ Method(_PSD,0)
+ {
+ If ( LNot(PSDF) )
+ {
+ Store (TCNT, Index(DerefOf(Index(HPSD, 0)),4))
+ Store (TCNT, Index(DerefOf(Index(SPSD, 0)),4))
+ Store (Ones, PSDF)
+ }
+ If(And(PDC0,0x0800))
+ {
+ Return(HPSD)
+ }
+ Return(SPSD)
+ }
+ Name(HPSD,Package() // HW_ALL
+ {
+ Package(){5, 0, 0, 0xFE, 0x80}
+ })
+ Name(SPSD,Package() // SW_ALL
+ {
+ Package(){5, 0, 0, 0xFC, 0x80}
+ })
+ }
+
+ Scope(\_PR.CPU7)
+ {
+ Method(_PPC,0)
+ {
+ Return(\_PR.CPU0._PPC) // Return CPU0 _PPC value.
+ }
+
+ Method(_PCT,0)
+ {
+ Return(\_PR.CPU0._PCT) // Return CPU0 _PCT value.
+ }
+
+ Method(_PSS,0)
+ {
+ Return(\_PR.CPU0._PSS) // Return CPU0 _PSS.
+ }
+
+ Name (PSDF, 0)
+ //
+ // The _PSD object provides information to the OSPM related
+ // to P-State coordination between processors in a multi-processor
+ // configurations.
+ //
+ Method(_PSD,0)
+ {
+ If ( LNot(PSDF) )
+ {
+ Store (TCNT, Index(DerefOf(Index(HPSD, 0)),4))
+ Store (TCNT, Index(DerefOf(Index(SPSD, 0)),4))
+ Store (Ones, PSDF)
+ }
+ If(And(PDC0,0x0800))
+ {
+ Return(HPSD)
+ }
+ Return(SPSD)
+ }
+ Name(HPSD,Package() // HW_ALL
+ {
+ Package(){5, 0, 0, 0xFE, 0x80}
+ })
+ Name(SPSD,Package() // SW_ALL
+ {
+ Package(){5, 0, 0, 0xFC, 0x80}
+ })
+ }
+
+} // End of Definition Block
diff --git a/ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/ApTst.asl b/ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/ApTst.asl
new file mode 100644
index 0000000..13972c2
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/ApTst.asl
@@ -0,0 +1,481 @@
+/*++
+ 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
+--*/
+
+/*++
+
+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.
+
+Module Name:
+
+ ApTst.asl
+
+Abstract:
+
+ Intel Processor Power Management ACPI Code
+
+ WARNING: You are authorized and licensed to install and use this BIOS code
+ ONLY on an IST PC. This utility may damage any system that does not
+ meet these requirements.
+
+ An IST PC is a computer which
+ (1) Is capable of seamlessly and automatically transitioning among
+ multiple performance states (potentially operating at different
+ efficiency ratings) based upon power source changes, END user
+ preference, processor performance demand, and thermal conditions; and
+ (2) Includes an Intel Pentium II processors, Intel Pentium III
+ processor, Mobile Intel Pentium III Processor-M, Mobile Intel Pentium 4
+ Processor-M, Intel Pentium M Processor, or any other future Intel
+ processors that incorporates the capability to transition between
+ different performance states by altering some, or any combination of,
+ the following processor attributes: core voltage, core frequency, bus
+ frequency, number of processor cores available, or any other attribute
+ that changes the efficiency (instructions/unit time-power) at which the
+ processor operates.
+
+--*/
+
+
+DefinitionBlock(
+ "APTST.aml",
+ "SSDT",
+ 0x01,
+ "PmRef",
+ "ApTst",
+ 0x3000
+ )
+{
+ External(\_PR.CPU1, DeviceObj)
+ External(\_PR.CPU2, DeviceObj)
+ External(\_PR.CPU3, DeviceObj)
+ External(\_PR.CPU4, DeviceObj)
+ External(\_PR.CPU5, DeviceObj)
+ External(\_PR.CPU6, DeviceObj)
+ External(\_PR.CPU7, DeviceObj)
+ External(\_PR.CPU0._PTC)
+ External(\_PR.CPU0._TSS)
+ External(PDC0)
+ External(CFGD)
+ External(TCNT)
+
+ Scope(\_PR.CPU1)
+ {
+ Name(_TPC, 0) // All T-States are available
+
+ //
+ // T-State Control/Status interface
+ //
+ Method(_PTC, 0)
+ {
+ Return(\_PR.CPU0._PTC)
+ }
+
+ Method(_TSS, 0)
+ {
+ Return(\_PR.CPU0._TSS)
+ }
+
+ //
+ // T-State Dependency
+ //
+ Method(_TSD, 0)
+ {
+ //
+ // IF four cores are supported/enabled && !(direct access to MSR)
+ // Report 4 processors and SW_ANY as the coordination
+ // IF two cores are supported/enabled && !(direct access to MSR)
+ // Report 2 processors and SW_ANY as the coordination type
+ // ELSE
+ // Report 1 processor and SW_ALL as the coordination type (domain 1)
+ //
+ // PDCx[2] = OSPM is capable of direct access to On
+ // Demand throttling MSR
+ //
+
+ If(LNot(And(PDC0,4)))
+ {
+ Return(Package(){ // SW_ANY
+ Package(){
+ 5, // # entries.
+ 0, // Revision.
+ 0, // Domain #.
+ 0xFD, // Coord Type- SW_ANY
+ TCNT // # processors.
+ }
+ })
+ }
+ Return(Package(){ // SW_ALL
+ Package(){
+ 5, // # entries.
+ 0, // Revision.
+ 1, // Domain #.
+ 0xFC, // Coord Type- SW_ALL
+ 1 // # processors.
+ }
+ })
+ }
+ } // End of CPU1
+
+
+ Scope(\_PR.CPU2)
+ {
+ Name(_TPC, 0) // All T-States are available
+
+ //
+ // T-State Control/Status interface
+ //
+ Method(_PTC, 0)
+ {
+ Return(\_PR.CPU0._PTC)
+ }
+
+ Method(_TSS, 0)
+ {
+ Return(\_PR.CPU0._TSS)
+ }
+
+ //
+ // T-State Dependency
+ //
+ Method(_TSD, 0)
+ {
+ //
+ // IF four cores are supported/enabled && !(direct access to MSR)
+ // Report 4 processors and SW_ANY as the coordination
+ // IF two cores are supported/enabled && !(direct access to MSR)
+ // Report 2 processors and SW_ANY as the coordination type
+ // ELSE
+ // Report 1 processor and SW_ALL as the coordination type (domain 2)
+ //
+ // PDCx[2] = OSPM is capable of direct access to On
+ // Demand throttling MSR
+ //
+
+ If(LNot(And(PDC0,4)))
+ {
+ Return(Package(){ // SW_ANY
+ Package(){
+ 5, // # entries.
+ 0, // Revision.
+ 0, // Domain #.
+ 0xFD, // Coord Type- SW_ANY
+ TCNT // # processors.
+ }
+ })
+ }
+ Return(Package(){ // SW_ALL
+ Package(){
+ 5, // # entries.
+ 0, // Revision.
+ 2, // Domain #.
+ 0xFC, // Coord Type- SW_ALL
+ 1 // # processors.
+ }
+ })
+ }
+ } // End of CPU2
+
+
+ Scope(\_PR.CPU3)
+ {
+ Name(_TPC, 0) // All T-States are available
+
+ //
+ // T-State Control/Status interface
+ //
+ Method(_PTC, 0)
+ {
+ Return(\_PR.CPU0._PTC)
+ }
+
+ Method(_TSS, 0)
+ {
+ Return(\_PR.CPU0._TSS)
+ }
+
+ //
+ // T-State Dependency
+ //
+ Method(_TSD, 0)
+ {
+ //
+ // IF four cores are supported/enabled && !(direct access to MSR)
+ // Report 4 processors and SW_ANY as the coordination
+ // IF two cores are supported/enabled && !(direct access to MSR)
+ // Report 2 processors and SW_ANY as the coordination type
+ // ELSE
+ // Report 1 processor and SW_ALL as the coordination type (domain 3)
+ //
+ // PDCx[2] = OSPM is capable of direct access to On
+ // Demand throttling MSR
+ //
+
+ If(LNot(And(PDC0,4)))
+ {
+ Return(Package(){ // SW_ANY
+ Package(){
+ 5, // # entries.
+ 0, // Revision.
+ 0, // Domain #.
+ 0xFD, // Coord Type- SW_ANY
+ TCNT // # processors.
+ }
+ })
+ }
+ Return(Package(){ // SW_ALL
+ Package(){
+ 5, // # entries.
+ 0, // Revision.
+ 3, // Domain #.
+ 0xFC, // Coord Type- SW_ALL
+ 1 // # processors.
+ }
+ })
+ }
+ } // End of CPU3
+
+ Scope(\_PR.CPU4)
+ {
+ Name(_TPC, 0) // All T-States are available
+
+ //
+ // T-State Control/Status interface
+ //
+ Method(_PTC, 0)
+ {
+ Return(\_PR.CPU0._PTC)
+ }
+
+ Method(_TSS, 0)
+ {
+ Return(\_PR.CPU0._TSS)
+ }
+
+ //
+ // T-State Dependency
+ //
+ Method(_TSD, 0)
+ {
+ //
+ // IF four cores are supported/enabled && !(direct access to MSR)
+ // Report 4 processors and SW_ANY as the coordination
+ // IF two cores are supported/enabled && !(direct access to MSR)
+ // Report 2 processors and SW_ANY as the coordination type
+ // ELSE
+ // Report 1 processor and SW_ALL as the coordination type (domain 3)
+ //
+ // PDCx[2] = OSPM is capable of direct access to On
+ // Demand throttling MSR
+ //
+
+ If(LNot(And(PDC0,4)))
+ {
+ Return(Package(){ // SW_ANY
+ Package(){
+ 5, // # entries.
+ 0, // Revision.
+ 0, // Domain #.
+ 0xFD, // Coord Type- SW_ANY
+ TCNT // # processors.
+ }
+ })
+ }
+ Return(Package(){ // SW_ALL
+ Package(){
+ 5, // # entries.
+ 0, // Revision.
+ 4, // Domain #.
+ 0xFC, // Coord Type- SW_ALL
+ 1 // # processors.
+ }
+ })
+ }
+ } // End of CPU4
+
+ Scope(\_PR.CPU5)
+ {
+ Name(_TPC, 0) // All T-States are available
+
+ //
+ // T-State Control/Status interface
+ //
+ Method(_PTC, 0)
+ {
+ Return(\_PR.CPU0._PTC)
+ }
+
+ Method(_TSS, 0)
+ {
+ Return(\_PR.CPU0._TSS)
+ }
+
+ //
+ // T-State Dependency
+ //
+ Method(_TSD, 0)
+ {
+ //
+ // IF four cores are supported/enabled && !(direct access to MSR)
+ // Report 4 processors and SW_ANY as the coordination
+ // IF two cores are supported/enabled && !(direct access to MSR)
+ // Report 2 processors and SW_ANY as the coordination type
+ // ELSE
+ // Report 1 processor and SW_ALL as the coordination type (domain 3)
+ //
+ // PDCx[2] = OSPM is capable of direct access to On
+ // Demand throttling MSR
+ //
+
+ If(LNot(And(PDC0,4)))
+ {
+ Return(Package(){ // SW_ANY
+ Package(){
+ 5, // # entries.
+ 0, // Revision.
+ 0, // Domain #.
+ 0xFD, // Coord Type- SW_ANY
+ TCNT // # processors.
+ }
+ })
+ }
+ Return(Package(){ // SW_ALL
+ Package(){
+ 5, // # entries.
+ 0, // Revision.
+ 5, // Domain #.
+ 0xFC, // Coord Type- SW_ALL
+ 1 // # processors.
+ }
+ })
+ }
+ } // End of CPU5
+
+ Scope(\_PR.CPU6)
+ {
+ Name(_TPC, 0) // All T-States are available
+
+ //
+ // T-State Control/Status interface
+ //
+ Method(_PTC, 0)
+ {
+ Return(\_PR.CPU0._PTC)
+ }
+
+ Method(_TSS, 0)
+ {
+ Return(\_PR.CPU0._TSS)
+ }
+
+ //
+ // T-State Dependency
+ //
+ Method(_TSD, 0)
+ {
+ //
+ // IF four cores are supported/enabled && !(direct access to MSR)
+ // Report 4 processors and SW_ANY as the coordination
+ // IF two cores are supported/enabled && !(direct access to MSR)
+ // Report 2 processors and SW_ANY as the coordination type
+ // ELSE
+ // Report 1 processor and SW_ALL as the coordination type (domain 3)
+ //
+ // PDCx[2] = OSPM is capable of direct access to On
+ // Demand throttling MSR
+ //
+
+ If(LNot(And(PDC0,4)))
+ {
+ Return(Package(){ // SW_ANY
+ Package(){
+ 5, // # entries.
+ 0, // Revision.
+ 0, // Domain #.
+ 0xFD, // Coord Type- SW_ANY
+ TCNT // # processors.
+ }
+ })
+ }
+ Return(Package(){ // SW_ALL
+ Package(){
+ 5, // # entries.
+ 0, // Revision.
+ 6, // Domain #.
+ 0xFC, // Coord Type- SW_ALL
+ 1 // # processors.
+ }
+ })
+ }
+ } // End of CPU6
+
+ Scope(\_PR.CPU7)
+ {
+ Name(_TPC, 0) // All T-States are available
+
+ //
+ // T-State Control/Status interface
+ //
+ Method(_PTC, 0)
+ {
+ Return(\_PR.CPU0._PTC)
+ }
+
+ Method(_TSS, 0)
+ {
+ Return(\_PR.CPU0._TSS)
+ }
+
+ //
+ // T-State Dependency
+ //
+ Method(_TSD, 0)
+ {
+ //
+ // IF four cores are supported/enabled && !(direct access to MSR)
+ // Report 4 processors and SW_ANY as the coordination
+ // IF two cores are supported/enabled && !(direct access to MSR)
+ // Report 2 processors and SW_ANY as the coordination type
+ // ELSE
+ // Report 1 processor and SW_ALL as the coordination type (domain 3)
+ //
+ // PDCx[2] = OSPM is capable of direct access to On
+ // Demand throttling MSR
+ //
+
+ If(LNot(And(PDC0,4)))
+ {
+ Return(Package(){ // SW_ANY
+ Package(){
+ 5, // # entries.
+ 0, // Revision.
+ 0, // Domain #.
+ 0xFD, // Coord Type- SW_ANY
+ TCNT // # processors.
+ }
+ })
+ }
+ Return(Package(){ // SW_ALL
+ Package(){
+ 5, // # entries.
+ 0, // Revision.
+ 7, // Domain #.
+ 0xFC, // Coord Type- SW_ALL
+ 1 // # processors.
+ }
+ })
+ }
+ } // End of CPU7
+} // End of Definition Block
+
diff --git a/ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/Cpu0Cst.asl b/ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/Cpu0Cst.asl
new file mode 100644
index 0000000..6c0c48a
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/Cpu0Cst.asl
@@ -0,0 +1,319 @@
+/*++
+ 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
+--*/
+
+/*++
+
+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.
+
+Module Name:
+
+ Cpu0Cst.asl
+
+Abstract:
+
+ Intel Processor Power Management ACPI Code
+
+ WARNING: You are authorized and licensed to install and use this BIOS code
+ ONLY on an IST PC. This utility may damage any system that does not
+ meet these requirements.
+
+ An IST PC is a computer which
+ (1) Is capable of seamlessly and automatically transitioning among
+ multiple performance states (potentially operating at different
+ efficiency ratings) based upon power source changes, END user
+ preference, processor performance demand, and thermal conditions; and
+ (2) Includes an Intel Pentium II processors, Intel Pentium III
+ processor, Mobile Intel Pentium III Processor-M, Mobile Intel Pentium 4
+ Processor-M, Intel Pentium M Processor, or any other future Intel
+ processors that incorporates the capability to transition between
+ different performance states by altering some, or any combination of,
+ the following processor attributes: core voltage, core frequency, bus
+ frequency, number of processor cores available, or any other attribute
+ that changes the efficiency (instructions/unit time-power) at which the
+ processor operates.
+
+--*/
+
+
+#include "PowerMgmtDefinitions.h"
+
+DefinitionBlock (
+ "CPU0CST.aml",
+ "SSDT",
+ 1,
+ "PmRef",
+ "Cpu0Cst",
+ 0x3001
+ )
+{
+External(\_PR.CPU0, DeviceObj)
+External(PWRS)
+External(CFGD)
+External(PDC0)
+External(FMBL)
+External(FEMD)
+External(PFLV)
+External(C3MW) // Mwait Hint value for C3
+External(C6MW) // Mwait Hint value for C6
+External(C7MW) // Mwait Hint value for C7
+External(CDMW) // Mwait Hint value for C8/C9/C10
+External(C3LT) // Latency value for C3
+External(C6LT) // Latency Value for C6
+External(C7LT) // Latency Value for C7
+External(CDLT) // Latency Value for C8/C9/C10
+External(CDLV) // IO Level value for C8/C9/C10
+External(CDPW) // Power value for C8/C9/C10
+
+Scope(\_PR.CPU0)
+{
+ //
+ // Create Temp packages for each C-state and Initialize them to default IO_LVL
+ //
+ // C1 Temp Package (C1 - HLT)
+ //
+ Name ( C1TM, Package()
+ {
+ ResourceTemplate () {Register(FFixedHW, 0, 0, 0)},
+ 1,
+ C1_LATENCY,
+ C1_POWER
+ })
+ //
+ // C3 Temp Package
+ //
+ Name ( C3TM, Package()
+ {
+ ResourceTemplate () {Register(SystemIO, 8, 0, PCH_ACPI_LV2)},
+ 2,
+ 0,
+ C3_POWER
+ })
+ //
+ // C6 Temp Package
+ //
+ Name ( C6TM, Package()
+ {
+ ResourceTemplate () {Register(SystemIO, 8, 0, PCH_ACPI_LV3)},
+ 2,
+ 0,
+ C6_POWER
+ })
+
+ //
+ // C7 Temp Package
+ //
+ Name ( C7TM, Package()
+ {
+ ResourceTemplate () {Register(SystemIO, 8, 0, PCH_ACPI_LV4)},
+ 2,
+ 0,
+ C7_POWER
+ })
+
+ //
+ // CD Temp Package - Deep C-states - covers C8/C9/C10
+ //
+ Name ( CDTM, Package()
+ {
+ ResourceTemplate () {Register(SystemIO, 8, 0, PCH_ACPI_LV4)},
+ 3,
+ 0,
+ 0
+ })
+ //
+ // ResourceTemplate for MWait Extentions Supported.
+ //
+ Name ( MWES, ResourceTemplate(){Register(FFixedHW, 1, 2, 0x00, 1)})
+ //
+ // Valid/Invalid Flags for ACPI C2 and C3
+ //
+ Name (AC2V, 0)
+ Name (AC3V, 0)
+ //
+ // Package for reporting 3 C-states
+ //
+ Name ( C3ST, Package()
+ {
+ 3,
+ Package() {},
+ Package() {},
+ Package() {}
+ })
+ //
+ // Package for reporting 2 C-states
+ //
+ Name ( C2ST, Package()
+ {
+ 2,
+ Package() {},
+ Package() {}
+ })
+ //
+ // Package for reporting 1 C-state
+ //
+ Name ( C1ST, Package()
+ {
+ 1,
+ Package() {}
+ })
+ //
+ // C-state initialization flag
+ //
+ Name(CSTF, 0)
+ //
+ // Lake Tiny Gear control setting (deafult value for Gear1)
+ //
+ Name (GEAR, 0)
+ //
+ // Returns the C-state table based on platform configuration.
+ // This method is serialized since it uses various global packages and updates them in run time to return the current C-state table.
+ //
+ Method (_CST, 0, Serialized)
+ {
+ If(LNot(CSTF))
+ {
+ //
+ // First call to _CST.
+ // Update Latency Values for C3/C6/C7/CD based on the Latency values passed through PPM NVS
+ //
+ Store (C3LT, Index(C3TM, 2))
+ Store (C6LT, Index(C6TM, 2))
+ Store (C7LT, Index(C7TM, 2))
+ Store (CDLT, Index(CDTM, 2))
+ //
+ // Update the IO_LVL and Power values in CD temp package
+ //
+ Store (CDPW, Index(CDTM, 3))
+ Store (CDLV, Index (DerefOf (Index (CDTM, 0)),7))
+ //
+ // CFGD[11] = 1 - MWAIT extensions supported
+ // PDCx[9] = 1 - OS supports MWAIT extensions
+ // PDCx[8] = 1 - OS supports MWAIT for C1 (Inferred from PDCx[9] = 1.)
+ //
+ If(LAnd(And(CFGD, PPM_MWAIT_EXT), And(PDC0,0x200)))
+ {
+ //
+ // Processor MWAIT extensions supported and OS supports MWAIT extensions
+ // 1. Replace the IO LVL ResourceTemplate of C1TM, C3TM, C6TM, C7TM, CDTM with MWAIT EXT ResourceTemplate (FFixedHW)
+ // 2. Update the Mwait Hint Values for C3/C6/C7/CD based on the Latency values passed through PPM NVS
+ //
+
+ Store (MWES, Index (C1TM, 0))
+ Store (MWES, Index (C3TM, 0))
+ Store (MWES, Index (C6TM, 0))
+ Store (MWES, Index (C7TM, 0))
+ Store (MWES, Index (CDTM, 0))
+
+ Store (C3MW, Index (DerefOf (Index (C3TM, 0)),7))
+ Store (C6MW, Index (DerefOf (Index (C6TM, 0)),7))
+ Store (C7MW, Index (DerefOf (Index (C7TM, 0)),7))
+ Store (CDMW, Index (DerefOf (Index (CDTM, 0)),7))
+ }
+ ElseIf (LAnd(And(CFGD, PPM_MWAIT_EXT), And(PDC0,0x100)))
+ {
+ //
+ // Update C1 temp package ResourceTemplate if OS supports Mwait for C1
+ //
+ Store (MWES, Index (C1TM, 0))
+ }
+
+ Store (Ones, CSTF)
+ }
+ //
+ // Initialize the ACPI C2, C3 Valid/Invalid flags to Invalid (0)
+ //
+ Store(Zero, AC2V)
+ Store(Zero, AC3V)
+ //
+ // Create C state Package with Acpi C1= C1,ACPI C2=MaxSupported(C6,C3,C7),ACPI C3=MaxSupported(C8,C9,C10).
+ // It is safe to assume C1 always supported if we enable C-states.
+ //
+ Store (C1TM, Index (C3ST,1))
+
+ If(And(CFGD,PPM_C7))
+ {
+ Store (C7TM, Index (C3ST,2))
+ Store (Ones, AC2V)
+ }ElseIf(And(CFGD,PPM_C6))
+ {
+ Store (C6TM, Index (C3ST,2))
+ Store (Ones, AC2V)
+ }ElseIf(And(CFGD,PPM_C3))
+ {
+ Store (C3TM, Index (C3ST,2))
+ Store (Ones, AC2V)
+ }
+ If(And(CFGD,PPM_CD)) {
+ Store (CDTM, Index (C3ST,3))
+ Store (Ones, AC3V)
+ }
+ //
+ // Modify the ACPI C2 and C3 states if LakeTiny GEAR2 or GEAR3. GEAR1- No Change
+ //
+ If(LEqual (GEAR, 1))
+ {
+ //
+ // GEAR2 - Deepest C-state is replaced with C3 and with C1 (if C3 not supported)
+ //
+ If (And(CFGD,PPM_C3))
+ {
+ Store (C3TM, Index (C3ST,2))
+ Store (Ones, AC2V)
+ Store (Zero, AC3V)
+ }
+ Else
+ {
+ Store (Zero, AC2V)
+ Store (Zero, AC3V)
+ }
+ }
+ If(LEqual (GEAR, 2))
+ {
+ //
+ // GEAR3 - Replace all C-states with C1
+ //
+ Store (Zero, AC2V)
+ Store (Zero, AC3V)
+ }
+
+ //
+ // Filter and return the final C-state package
+ //
+ If(LAnd(AC2V, AC3V))
+ {
+ Return (C3ST)
+ }
+ ElseIf(AC2V)
+ {
+ Store (DerefOf (Index (C3ST,1)), Index (C2ST,1))
+ Store (DerefOf (Index (C3ST,2)), Index (C2ST,2))
+ Return (C2ST)
+ }
+ ElseIf(AC3V)
+ {
+ Store (DerefOf (Index (C3ST,1)), Index (C2ST,1))
+ Store (DerefOf (Index (C3ST,3)), Index (C2ST,2))
+ Store (2, Index (DerefOf (Index (C2ST, 2)),1))
+ Return (C2ST)
+ }
+ Else
+ {
+ Store (DerefOf (Index (C3ST,1)), Index (C1ST,1))
+ Return (C1ST)
+ }
+ }
+}
+}
diff --git a/ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/Cpu0Ist.asl b/ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/Cpu0Ist.asl
new file mode 100644
index 0000000..83b5294
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/Cpu0Ist.asl
@@ -0,0 +1,163 @@
+/*++
+ 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
+--*/
+
+/*++
+
+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.
+
+Module Name:
+
+ Cpu0Ist.asl
+
+Abstract:
+
+ Intel Processor Power Management ACPI Code
+
+ WARNING: You are authorized and licensed to install and use this BIOS code
+ ONLY on an IST PC. This utility may damage any system that does not
+ meet these requirements.
+
+ An IST PC is a computer which
+ (1) Is capable of seamlessly and automatically transitioning among
+ multiple performance states (potentially operating at different
+ efficiency ratings) based upon power source changes, END user
+ preference, processor performance demand, and thermal conditions; and
+ (2) Includes an Intel Pentium II processors, Intel Pentium III
+ processor, Mobile Intel Pentium III Processor-M, Mobile Intel Pentium 4
+ Processor-M, Intel Pentium M Processor, or any other future Intel
+ processors that incorporates the capability to transition between
+ different performance states by altering some, or any combination of,
+ the following processor attributes: core voltage, core frequency, bus
+ frequency, number of processor cores available, or any other attribute
+ that changes the efficiency (instructions/unit time-power) at which the
+ processor operates.
+
+--*/
+
+
+DefinitionBlock (
+ "CPU0IST.aml",
+ "SSDT",
+ 0x01,
+ "PmRef",
+ "Cpu0Ist",
+ 0x3000
+ )
+{
+ External (\_PR.CPU0, DeviceObj)
+ External (\_PR.CPPC)
+ External (PDC0)
+ External (CFGD)
+ External (TCNT)
+ External (MPMF)
+ Scope(\_PR.CPU0)
+ {
+ //
+ // Report supported P-States.
+ //
+ Name(_PPC, 0)
+
+ //
+ // NOTE: For CMP systems; this table is not loaded unless
+ // the required driver support is present.
+ // So, we do not check for those cases here.
+ //
+ // CFGD[0] = GV3 Capable/Enabled
+ // PDCx[0] = OS Capable of Hardware P-State control
+ //
+ Method(_PCT,0)
+ {
+ // Update the _PPC value
+ //
+ Store (\_PR.CPPC, \_PR.CPU0._PPC)
+
+ If(LAnd(And(CFGD,0x0001), And(PDC0,0x0001)))
+ {
+ Return(Package() // Native Mode
+ {
+ ResourceTemplate(){Register(FfixedHW, 0, 0, 0)},
+ ResourceTemplate(){Register(FfixedHW, 0, 0, 0)}
+ })
+ }
+ }
+
+ Name(_PSS,Package()
+ {
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+ Package(){0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000, 0x80000000}
+ })
+
+ Name (PSDF, 0)
+ //
+ // The _PSD object provides information to the OSPM related
+ // to P-State coordination between processors in a multi-processor
+ // configurations.
+ //
+ Method(_PSD,0)
+ {
+ If ( LNot(PSDF) )
+ {
+ Store (TCNT, Index(DerefOf(Index(HPSD, 0)),4))
+ Store (TCNT, Index(DerefOf(Index(SPSD, 0)),4))
+ Store (Ones, PSDF)
+ }
+
+ If(And(PDC0,0x0800))
+ {
+ Return(HPSD)
+ }
+ Return(SPSD)
+ }
+ Name(HPSD,Package() // HW_ALL
+ {
+ Package(){5, 0, 0, 0xFE, 0x80}
+ })
+ Name(SPSD,Package() // SW_ALL
+ {
+ Package(){5, 0, 0, 0xFC, 0x80}
+ })
+ }
+} // End of Definition Block
diff --git a/ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/Cpu0Tst.asl b/ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/Cpu0Tst.asl
new file mode 100644
index 0000000..a695091
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/Cpu0Tst.asl
@@ -0,0 +1,258 @@
+/*++
+ 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
+--*/
+
+/*++
+
+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.
+
+Module Name:
+
+ Cpu0Tst.asl
+
+Abstract:
+
+ Intel Processor Power Management ACPI Code
+
+ WARNING: You are authorized and licensed to install and use this BIOS code
+ ONLY on an IST PC. This utility may damage any system that does not
+ meet these requirements.
+
+ An IST PC is a computer which
+ (1) Is capable of seamlessly and automatically transitioning among
+ multiple performance states (potentially operating at different
+ efficiency ratings) based upon power source changes, END user
+ preference, processor performance demand, and thermal conditions; and
+ (2) Includes an Intel Pentium II processors, Intel Pentium III
+ processor, Mobile Intel Pentium III Processor-M, Mobile Intel Pentium 4
+ Processor-M, Intel Pentium M Processor, or any other future Intel
+ processors that incorporates the capability to transition between
+ different performance states by altering some, or any combination of,
+ the following processor attributes: core voltage, core frequency, bus
+ frequency, number of processor cores available, or any other attribute
+ that changes the efficiency (instructions/unit time-power) at which the
+ processor operates.
+
+--*/
+
+
+
+#include "PowerMgmtDefinitions.h"
+
+DefinitionBlock(
+ "CPU0TST.aml",
+ "SSDT",
+ 0x01,
+ "PmRef",
+ "Cpu0Tst",
+ 0x3000
+ )
+{
+ External(\_PR.CPU0, DeviceObj)
+ External(PDC0)
+ External(CFGD)
+ External(_PSS)
+ External (TCNT)
+
+ Scope(\_PR.CPU0)
+ {
+ Name(_TPC, 0) // All T-States are available
+
+ //
+ // T-State Control/Status interface
+ //
+ Method(_PTC, 0)
+ {
+ //
+ // IF OSPM is capable of direct access to MSR
+ // Report MSR interface
+ // ELSE
+ // Report I/O interface
+ //
+ // PDCx[2] = OSPM is capable of direct access to On
+ // Demand throttling MSR
+ //
+ If(And(PDC0, 0x0004)) {
+
+ Return(Package() {
+ ResourceTemplate(){Register(FFixedHW, 0, 0, 0)},
+ ResourceTemplate(){Register(FFixedHW, 0, 0, 0)}
+ })
+ }
+
+ Return(Package() {
+ ResourceTemplate(){Register(SystemIO, 5, 0, PCH_ACPI_PBLK)},
+ ResourceTemplate(){Register(SystemIO, 5, 0, PCH_ACPI_PBLK)}
+ })
+ }
+
+ //
+ // _TSS package for fine-grained T-State control.
+ // "Power" fields are replaced with real values by the first
+ // call of _TSS method.
+ //
+ Name(TSMF, Package() {
+ Package(){100, 1000, 0, 0x00, 0},
+ Package(){ 94, 940, 0, 0x1F, 0},
+ Package(){ 88, 880, 0, 0x1E, 0},
+ Package(){ 82, 820, 0, 0x1D, 0},
+ Package(){ 75, 760, 0, 0x1C, 0},
+ Package(){ 69, 700, 0, 0x1B, 0},
+ Package(){ 63, 640, 0, 0x1A, 0},
+ Package(){ 57, 580, 0, 0x19, 0},
+ Package(){ 50, 520, 0, 0x18, 0},
+ Package(){ 44, 460, 0, 0x17, 0},
+ Package(){ 38, 400, 0, 0x16, 0},
+ Package(){ 32, 340, 0, 0x15, 0},
+ Package(){ 25, 280, 0, 0x14, 0},
+ Package(){ 19, 220, 0, 0x13, 0},
+ Package(){ 13, 160, 0, 0x12, 0},
+ Package(){ 7, 100, 0, 0x11, 0}
+ })
+
+ //
+ // _TSS package for T-State control (Coarse grained)
+ // "Power" fields are replaced with real values by the first
+ // call of _TSS method.
+ //
+ Name(TSMC, Package() {
+ Package(){100, 1000, 0, 0x00, 0},
+ Package(){ 88, 875, 0, 0x1E, 0},
+ Package(){ 75, 750, 0, 0x1C, 0},
+ Package(){ 63, 625, 0, 0x1A, 0},
+ Package(){ 50, 500, 0, 0x18, 0},
+ Package(){ 38, 375, 0, 0x16, 0},
+ Package(){ 25, 250, 0, 0x14, 0},
+ Package(){ 13, 125, 0, 0x12, 0}
+ })
+
+ Name(TSSF, 0) // Flag for TSIF/TSIC/TSMF/TSMC initialization
+ Mutex(TSMO, 0) // Mutex object to ensure the _TSS initalization code is only executed once
+ Method(_TSS, 0)
+ {
+ //
+ // Update "Power" fields of TSIC or TSIF or TSMC or TSMF with the LFM
+ // power data IF _PSS is available
+ // Power caluclation:
+ // n - Number of T-states available
+ // _TSS(x).power = LFM.Power * (n-x)/n
+ //
+ IF (LAnd(LNot(TSSF),CondRefOf(_PSS)))
+ {
+ //
+ // Acquire Mutex to make sure the initialization happens only once.
+ //
+ Acquire (TSMO, 0xFFFF)
+ //
+ // Only one thread will be able to acquire the mutex at a time, but the other threads which have acquired the mutex previously, will eventually try to execute the TSS initalization code.
+ // So, let's check if TSS has already been initalized once again. If its initalized, skip the initalization.
+ //
+ IF (LAnd(LNot(TSSF),CondRefOf(_PSS)))
+ {
+ Name ( LFMI, 0)
+ Store (SizeOf(_PSS), LFMI)
+ Decrement(LFMI) // Index of LFM entry in _PSS
+ Name ( LFMP, 0) //LFM Power from _PSS
+ Store ( DerefOf(Index(DerefOf(Index(_PSS,LFMI)),1)) , LFMP)
+ Store (0, Local0)
+
+ //
+ // Copy reference of appropiate TSS package based on Fine grained T-state support
+ // We'll update the power in the package directly (via the reference variable Local1)
+ //
+ // If Fine Grained T-states is enabled
+ // TSMF
+ // ELSE
+ // TSMC
+ //
+ If(And(CFGD,PPM_TSTATE_FINE_GRAINED))
+ {
+ Store ( RefOf(TSMF), Local1 )
+ Store ( SizeOf(TSMF),Local2 )
+ }
+ Else
+ {
+ Store ( RefOf(TSMC), Local1 )
+ Store ( SizeOf(TSMC),Local2 )
+ }
+
+ While(LLess(Local0, Local2))
+ {
+ Store(Divide(Multiply(LFMP, Subtract(Local2, Local0)), Local2),
+ Local4) // Power for this entry
+ Store(Local4,Index(DerefOf(Index(DerefOf(Local1),Local0)),1))
+ Increment(Local0)
+ }
+
+ Store(Ones, TSSF) // Set flag to indicate TSS table initalization is complete
+ }
+
+ Release (TSMO)
+
+ }
+ //
+ // If Fine Grained T-states is enabled
+ // Report TSMF
+ // ELSE
+ // Report TSMC
+ //
+ If(And(CFGD, PPM_TSTATE_FINE_GRAINED))
+ {
+ Return(TSMF)
+ }
+ Else
+ {
+ Return(TSMC)
+ }
+ }
+
+ //
+ // T-State Dependency
+ //
+ Method(_TSD, 0)
+ {
+ //
+ // IF !(direct access to MSR)
+ // Report SW_ANY as the coordination type
+ // ELSE
+ // Report SW_ALL as the coordination type
+ //
+ // PDCx[2] = OSPM is capable of direct access to On
+ // Demand throttling MSR
+ //
+ If (LNot(And(PDC0,4))) {
+ Return(Package(){ // SW_ANY
+ Package(){
+ 5, // # entries.
+ 0, // Revision.
+ 0, // Domain #.
+ 0xFD, // Coord Type- SW_ANY
+ TCNT // # processors.
+ }
+ })
+ }
+ Return(Package(){ // SW_ALL
+ Package(){
+ 5, // # entries.
+ 0, // Revision.
+ 0, // Domain #.
+ 0xFC, // Coord Type- SW_ALL
+ 1 // # processors.
+ }
+ })
+ }
+ }
+} // End of Definition Block
+
diff --git a/ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/CpuPm.asl b/ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/CpuPm.asl
new file mode 100644
index 0000000..2ba3e1b
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/CpuPm.asl
@@ -0,0 +1,1061 @@
+/*++
+ 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
+--*/
+
+/*++
+
+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.
+
+Module Name:
+
+ CpuPm.asl
+
+Abstract:
+
+ Intel Processor Power Management ACPI Code
+
+ WARNING: You are authorized and licensed to install and use this BIOS code
+ ONLY on an IST PC. This utility may damage any system that does not
+ meet these requirements.
+
+ An IST PC is a computer which
+ (1) Is capable of seamlessly and automatically transitioning among
+ multiple performance states (potentially operating at different
+ efficiency ratings) based upon power source changes, END user
+ preference, processor performance demand, and thermal conditions; and
+ (2) Includes an Intel Pentium II processors, Intel Pentium III
+ processor, Mobile Intel Pentium III Processor-M, Mobile Intel Pentium 4
+ Processor-M, Intel Pentium M Processor, or any other future Intel
+ processors that incorporates the capability to transition between
+ different performance states by altering some, or any combination of,
+ the following processor attributes: core voltage, core frequency, bus
+ frequency, number of processor cores available, or any other attribute
+ that changes the efficiency (instructions/unit time-power) at which the
+ processor operates.
+
+--*/
+
+#include "PowerMgmtDefinitions.h"
+
+DefinitionBlock (
+ "CPUPM.aml",
+ "SSDT",
+ 0x01,
+ "PmRef",
+ "CpuPm",
+ 0x3000
+ )
+{
+ External(\_PR.CPU0, DeviceObj)
+ External(\_PR.CPU1, DeviceObj)
+ External(\_PR.CPU2, DeviceObj)
+ External(\_PR.CPU3, DeviceObj)
+ External(\_PR.CPU4, DeviceObj)
+ External(\_PR.CPU5, DeviceObj)
+ External(\_PR.CPU6, DeviceObj)
+ External(\_PR.CPU7, DeviceObj)
+ External(\_PR.CPU0._PPC, IntObj)
+ External(SMIF)
+
+Scope(\)
+{
+
+ // Package of pointers to SSDT's
+ //
+ // First column is SSDT name, used for debug only.
+ // (First column must be EXACTLY eight characters.)
+ // Second column is physical address.
+ // Third column is table length.
+ //
+ // IF modifying this file, see warnings listed in ppminit.asm.
+ //
+ Name(SSDT,Package()
+ {
+ "CPU0IST ", 0x80000000, 0x80000000,
+ "APIST ", 0x80000000, 0x80000000,
+ "CPU0CST ", 0x80000000, 0x80000000,
+ "APCST ", 0x80000000, 0x80000000
+ })
+
+ Name(\PDC0,0x80000000) // CPU0 _PDC Flags.
+ Name(\PDC1,0x80000000) // CPU1 _PDC Flags.
+ Name(\PDC2,0x80000000) // CPU2 _PDC Flags.
+ Name(\PDC3,0x80000000) // CPU3 _PDC Flags.
+ Name(\PDC4,0x80000000) // CPU4 _PDC Flags.
+ Name(\PDC5,0x80000000) // CPU5 _PDC Flags.
+ Name(\PDC6,0x80000000) // CPU6 _PDC Flags.
+ Name(\PDC7,0x80000000) // CPU7 _PDC Flags.
+
+ Name(\SDTL,0x00) // Loaded SSDT Flags.
+}
+
+Scope(\_PR)
+{
+ //
+ // Define a Processor scope ACPI PPM GlobalNvs NVS Region
+ //
+ OperationRegion(PPMT,SystemMemory,0xFFFF0000,0xAA55)
+ Field(PPMT,AnyAcc,Lock,Preserve)
+ {
+ PGRV, 8, // (0) PPM GlobalNvs Revision
+ CFGD, 32, // CFGD - PpmFlags
+ Offset(6), // (5) Reserved
+ //
+ // Thermal Configuration Values
+ //
+ ACRT, 8, // (6) Auto Critical Trip Point
+ APSV, 8, // (7) Auto Passive Trip Point
+ AAC0, 8, // (8) Auto Active Trip Point
+ CPID, 32, // (9) CPUID
+ //
+ // ConfigTDP Value
+ //
+ CPPC, 8, // (13) Boot Mode vlues for _PPC
+ //
+ // ConfigTDP Level settngs
+ //
+ CCTP, 8, // (14) Custom ConfigTdp Enabled/Disabled
+ CLVL, 8, // (15) ConfigTdp Number Of Levels
+ CBMI, 8, // (16) CTDP Boot Mode Index
+ PL10, 16, // (17) CTDP Level 0 Power Limit1
+ PL20, 16, // (19) CTDP Level 0 Power Limit2
+ PLW0, 8, // (21) CTDP Level 0 Power Limit1 Time Window
+ CTC0, 8, // (22) CTDP Level 0 CTC
+ TAR0, 8, // (23) CTDP Level 0 TAR
+ PPC0, 8, // (24) CTDP Level 0 PPC
+ PL11, 16, // (25) CTDP Level 1 Power Limit1
+ PL21, 16, // (27) CTDP Level 1 Power Limit2
+ PLW1, 8, // (29) CTDP Level 1 Power Limit1 Time Window
+ CTC1, 8, // (30) CTDP Level 1 CTC
+ TAR1, 8, // (31) CTDP Level 1 TAR
+ PPC1, 8, // (32) CTDP Level 1 PPC
+ PL12, 16, // (33) CTDP Level 2 Power Limit1
+ PL22, 16, // (35) CTDP Level 2 Power Limit2
+ PLW2, 8, // (37) CTDP Level 2 Power Limit1 Time Window
+ CTC2, 8, // (38) CTDP Level 2 CTC
+ TAR2, 8, // (39) CTDP Level 2 TAR
+ PPC2, 8, // (40) CTDP Level 2 PPC
+ //
+ // Mwait Hints and Latency values for C3/C6/C7/C7S
+ //
+ C3MW, 8, // (41) Mwait Hint value for C3
+ C6MW, 8, // (42) Mwait Hint value for C6
+ C7MW, 8, // (43) Mwait Hint value for C7/C7s
+ CDMW, 8, // (44) Mwait Hint value for C8/C9/C10
+ C3LT, 16, // (45-46) Latency value for C3
+ C6LT, 16, // (47-48) Latency Value for C6
+ C7LT, 16, // (49-50) Latency Value for C7/C7S
+ CDLT, 16, // (51-52) Latency Value for C8/C9/C10
+ CDLV, 16, // (53-54) IO LVL value for C8/C9/C10
+ CDPW, 16, // (55-56) Power value for C8/C9/C10
+ MPMF, 8 // (57) MiscPowerManagementFlags
+ }
+}
+
+Scope(\_PR.CPU0)
+{
+ //
+ // Define handles for opregions (used by load.)
+ //
+ Name(HI0,0) // Handle to CPU0IST
+ Name(HC0,0) // Handle to CPU0CST
+
+ Method(_PDC,1)
+ {
+ //
+ // Update the _PPC value
+ //
+ if(CondRefOf(\_PR.CPU0._PPC)) {
+ Store (CPPC, \_PR.CPU0._PPC)
+ }
+ //
+ // Check and extract the _PDC information.
+ //
+ Store(CPDC(Arg0), Local0)
+ //
+ // Save the capability information and load tables as needed.
+ //
+ GCAP(Local0)
+ //
+ // Return status.
+ //
+ Return (Local0)
+ }
+
+ Method(_OSC, 4)
+ {
+ //
+ // Check and extract the _OSC information.
+ //
+ Store(COSC(Arg0, Arg1, Arg2, Arg3), Local0)
+ //
+ // Save the capability information and load tables as needed.
+ //
+ GCAP(Local0)
+ //
+ // Return status.
+ //
+ Return (Local0)
+ }
+
+ //
+ // Implement a generic Method to check _PDC information which may be called
+ // by any of the processor scopes. (The use of _PDC is deprecated in ACPI 3.
+ // in favor of _OSC. However, for backwards compatibility, _PDC may be
+ // implemented using _OSC as follows:)
+ //
+ Method(CPDC,1)
+ {
+ CreateDwordField (Arg0, 0, REVS)
+ CreateDwordField (Arg0, 4, SIZE)
+
+ //
+ // Local0 = Number of bytes for Arg0
+ //
+ Store (SizeOf (Arg0), Local0)
+
+ //
+ // Local1 = Number of Capabilities bytes in Arg0
+ //
+ Store (Subtract (Local0, 8), Local1)
+
+ //
+ // TEMP = Temporary field holding Capability DWORDs
+ //
+ CreateField (Arg0, 64, Multiply (Local1, 8), TEMP)
+
+ //
+ // Create the Status (STAT) buffer with the first DWORD = 0
+ // This is required as per ACPI 3.0 Spec which says the
+ // first DWORD is used to return errors defined by _OSC.
+ //
+ Name (STS0, Buffer () {0x00, 0x00, 0x00, 0x00})
+
+ //
+ // Concatenate the _PDC capabilities bytes to the STS0 Buffer
+ // and store them in a local variable for calling OSC
+ //
+ Concatenate (STS0, TEMP, Local2)
+
+ Return(COSC (ToUUID("4077A616-290C-47BE-9EBD-D87058713953"), REVS, SIZE, Local2))
+ }
+
+ //
+ // Implement a generic Method to check _OSC information which may be called
+ // by any of the processor scopes.
+ //
+ Method(COSC, 4)
+ {
+ //
+ // Point to Status DWORD in the Arg3 buffer (STATUS)
+ //
+ CreateDWordField(Arg3, 0, STS0)
+ //
+ // Point to Caps DWORDs of the Arg3 buffer (CAPABILITIES)
+ //
+ CreateDwordField(Arg3, 4, CAP0)
+
+ //
+ // _OSC needs to validate the UUID and Revision.
+ //
+ // IF Unrecognized UUID
+ // Return Unrecognized UUID _OSC Failure
+ // IF Unsupported Revision
+ // Return Unsupported Revision _OSC Failure
+ //
+ // STS0[0] = Reserved
+ // STS0[1] = _OSC Failure
+ // STS0[2] = Unrecognized UUID
+ // STS0[3] = Unsupported Revision
+ // STS0[4] = Capabilities masked
+ //
+ // Note: The comparison method used is necessary due to
+ // limitations of certain OSes which cannot perform direct
+ // buffer comparisons.
+ //
+ // Create a set of "Input" UUID fields.
+ //
+ CreateDwordField(Arg0, 0x0, IID0)
+ CreateDwordField(Arg0, 0x4, IID1)
+ CreateDwordField(Arg0, 0x8, IID2)
+ CreateDwordField(Arg0, 0xC, IID3)
+ //
+ // Create a set of "Expected" UUID fields.
+ //
+ Name(UID0, ToUUID("4077A616-290C-47BE-9EBD-D87058713953"))
+ CreateDwordField(UID0, 0x0, EID0)
+ CreateDwordField(UID0, 0x4, EID1)
+ CreateDwordField(UID0, 0x8, EID2)
+ CreateDwordField(UID0, 0xC, EID3)
+ //
+ // Verify the input UUID matches the expected UUID.
+ //
+ If(LNot(LAnd(LAnd(LEqual(IID0, EID0),LEqual(IID1, EID1)),LAnd(LEqual(IID2, EID2),LEqual(IID3, EID3)))))
+ {
+ //
+ // Return Unrecognized UUID _OSC Failure
+ //
+ Store (0x6, STS0)
+ Return (Arg3)
+ }
+
+ If(LNot(LEqual(Arg1,1)))
+ {
+ //
+ // Return Unsupported Revision _OSC Failure
+ //
+ Store (0xA, STS0)
+ Return (Arg3)
+ }
+
+ Return (Arg3)
+ }
+
+ //
+ // Get the capability information and load appropriate tables as needed.
+ //
+ Method(GCAP, 1)
+ {
+ //
+ // Point to Status DWORD in the Arg0 buffer (STATUS)
+ //
+ CreateDWordField(Arg0, 0, STS0)
+ //
+ // Point to Caps DWORDs of the Arg0 buffer (CAPABILITIES)
+ //
+ CreateDwordField(Arg0, 4, CAP0)
+
+ //
+ // If the UUID was unrecognized or the _OSC revision was unsupported,
+ // return without updating capabilities.
+ //
+ If(LOr(LEqual(STS0,0x6),LEqual(STS0,0xA)))
+ {
+ Return()
+ }
+
+ //
+ // Check if this is a query (BIT0 of Status = 1).
+ // If so, mask off the bits we support and return.
+ //
+ if (And(STS0, 1))
+ {
+ And(CAP0, 0xBFF, CAP0)
+ Return()
+ }
+
+ //
+ // Store result of PDC. (We clear out the MSB, which was just
+ // used as a placeholder for the compiler; and then "OR" the
+ // value in case we get multiple calls, each of which only
+ // reports partial support.)
+ //
+ Or(And(PDC0, 0x7FFFFFFF), CAP0, PDC0)
+
+ //
+ // Check IF the CST SSDTs should be loaded.
+ // CFGD[5:1] = C7, C6, C3, C1E, C1 Capable/Enabled
+ If(And(CFGD, PPM_C_STATES))
+ {
+ //
+ // Load the CST SSDTs if:
+ // (1) CMP capable/enabled
+ // (2) Driver supports multi-processor configurations
+ // (3) CPU0 CST ISDT is not already loaded
+ //
+ // CFGD[9] = Two or more cores enabled
+ // PDCx[3] = OS supports C1 and P-states in MP systems
+ // PDCx[4] = OS supports ind. C2/C3 in MP systems
+ // SDTL[1] = CPU0 CST SSDT Loaded
+ //
+ If(LAnd(LAnd(And(CFGD, PPM_CMP),And(PDC0,0x0018)),LNot(And(SDTL,0x02))))
+ {
+ //
+ // Flag the CST SSDT as loaded for CPU0
+ //
+ Or(SDTL, 0x02, SDTL)
+
+ OperationRegion(CST0,SystemMemory,DeRefOf(Index(SSDT,7)),DeRefOf(Index(SSDT,8)))
+ Load(CST0, HC0) // Dynamically load the CPU0CST SSDT
+ }
+ }
+
+ Return ()
+ }
+}
+
+
+Scope(\_PR.CPU1)
+{
+ //
+ // Define handles for opregions (used by load.)
+ //
+ Name(HI1,0) // Handle to APIST
+ Name(HC1,0) // Handle to APCST
+
+ Method(_PDC,1)
+ {
+ //
+ // Refer to \_PR.CPU0._PDC for description.
+ //
+ Store(\_PR.CPU0.CPDC(Arg0), Local0)
+ GCAP(Local0)
+ Return (Local0)
+ }
+
+ Method(_OSC, 4)
+ {
+ //
+ // Refer to \_PR.CPU0._OSC for description.
+ //
+ Store(\_PR.CPU0.COSC(Arg0, Arg1, Arg2, Arg3), Local0)
+ GCAP(Local0)
+ Return (Local0)
+ }
+
+ //
+ // Get the capability information and load appropriate tables as needed.
+ //
+ Method(GCAP, 1)
+ {
+ //
+ // Point to Status DWORD in the Arg0 buffer (STATUS)
+ //
+ CreateDWordField(Arg0, 0, STS1)
+ //
+ // Point to Caps DWORDs of the Arg0 buffer (CAPABILITIES)
+ //
+ CreateDwordField(Arg0, 4, CAP1)
+ //
+ // If the UUID was unrecognized or the _OSC revision was unsupported,
+ // return without updating capabilities.
+ //
+ If(LOr(LEqual(STS1,0x6),LEqual(STS1,0xA)))
+ {
+ Return()
+ }
+
+ //
+ // Check if this is a query (BIT0 of Status = 1).
+ // If so, mask off the bits we support and return.
+ //
+ if (And(STS1, 1))
+ {
+ And(CAP1, 0xBFF, CAP1)
+ Return()
+ }
+
+ //
+ // Store result of PDC. (We clear out the MSB, which was just
+ // used as a placeholder for the compiler; and then "OR" the
+ // value in case we get multiple calls, each of which only
+ // reports partial support.)
+ //
+ Or(And(PDC1, 0x7FFFFFFF), CAP1, PDC1)
+
+ //
+ // Attempt to dynamically load the IST SSDTs if:
+ // (1) Driver supports P-States in MP configurations
+ // (2) Driver supports direct HW P-State control
+ //
+ // PDCx[3] = OS supports C1 and P-states in MP systems
+ // PDCx[0] = OS supports direct access of the perf MSR
+ //
+ If(LEqual(And(PDC1, 0x0009), 0x0009))
+ {
+ APPT()
+ }
+
+ //
+ // Load the CST SSDTs if:
+ // (1) Driver supports multi-processor configurations
+ //
+ // PDCx[3] = OS supports C1 and P-states in MP systems
+ // PDCx[4] = OS supports ind. C2/C3 in MP systems
+ //
+ If(And(PDC1,0x0018))
+ {
+ APCT()
+ }
+
+ Store (PDC1, PDC0)
+
+ Return()
+ }
+
+ //
+ // Dynamically load the CST SSDTs if:
+ // (1) C-States are enabled
+ // (2) SSDT is not already loaded
+ //
+ // CFGD[5:1] = Basic C-States supported (C1, C1E, C3, C6, C7)
+ // SDTL[5] = AP CST SSDT Loaded
+ //
+ Method(APCT,0)
+ {
+ If(LAnd(And(CFGD,PPM_C_STATES),LNot(And(SDTL,0x20))))
+ {
+ //
+ // Flag the CST SSDT as loaded for the AP's
+ //
+ Or(SDTL, 0x20, SDTL)
+ //
+ // Dynamically load the APCST SSDT
+ //
+ OperationRegion(CST1,SystemMemory,DeRefOf(Index(SSDT,10)),DeRefOf(Index(SSDT,11)))
+ Load(CST1, HC1)
+ }
+ }
+
+ //
+ // Dynamically load the IST SSDTs if:
+ // (1) If GV3 capable and enabled
+ // (2) SSDT is not already loaded
+ //
+ // CFGD[0] = GV3 Capable/Enabled
+ // SDTL[4] = AP IST SSDT Loaded
+ //
+ Method(APPT,0)
+ {
+ If(LAnd(And(CFGD,PPM_EIST),LNot(And(SDTL,0x10))))
+ {
+ //
+ // Flag the IST SSDT as loaded for CPU0
+ //
+ Or(SDTL, 0x10, SDTL)
+
+ OperationRegion(IST1,SystemMemory,DeRefOf(Index(SSDT,4)),DeRefOf(Index(SSDT,5)))
+ Load(IST1, HI1) // Dynamically load the CPU1IST SSDT
+ }
+ }
+} // End CPU1
+
+
+Scope(\_PR.CPU2)
+{
+ Method(_PDC,1)
+ {
+ //
+ // Call the _PDC for CPU1.
+ //
+ Store(\_PR.CPU0.CPDC(Arg0), Local0)
+ GCAP(Local0)
+ Return (Local0)
+ }
+
+ Method(_OSC, 4)
+ {
+ //
+ // Call the _OSC for CPU1.
+ //
+ Store(\_PR.CPU0.COSC(Arg0, Arg1, Arg2, Arg3), Local0)
+ GCAP(Local0)
+ Return (Local0)
+ }
+
+ Method(GCAP,1)
+ {
+ // Point to Status DWORD in the Arg0 buffer (STATUS)
+ CreateDWordField(Arg0, 0, STS2)
+
+ // Point to Caps DWORDs of the Arg0 buffer (CAPABILITIES)
+ CreateDwordField(Arg0, 4, CAP2)
+
+ //
+ // If the UUID was unrecognized or the _OSC revision was unsupported,
+ // return without updating capabilities.
+ //
+ If(LOr(LEqual(STS2,0x6),LEqual(STS2,0xA)))
+ {
+ Return()
+ }
+
+ //
+ // Check if this is a query (BIT0 of Status = 1).
+ // If so, mask off the bits we support and return.
+ //
+ if (And(STS2, 1))
+ {
+ And(CAP2, 0xBFF, CAP2)
+ Return()
+ }
+
+ //
+ // Store result of PDC. (We clear out the MSB, which was just
+ // used as a placeholder for the compiler; and then "OR" the
+ // value in case we get multiple calls, each of which only
+ // reports partial support.)
+ //
+ Or(And(PDC2, 0x7FFFFFFF), CAP2, PDC2)
+ //
+ // Attempt to dynamically load the IST SSDTs if:
+ // (1) Driver supports P-States in MP configurations
+ // (2) Driver supports direct HW P-State control
+ //
+ // PDCx[3] = OS supports C1 and P-states in MP systems
+ // PDCx[0] = OS supports direct access of the perf MSR
+ //
+ If(LEqual(And(PDC2, 0x0009), 0x0009))
+ {
+ \_PR.CPU1.APPT()
+ }
+
+ //
+ // Load the CST SSDTs if:
+ // (1) Driver supports multi-processor configurations
+ //
+ // PDCx[3] = OS supports C1 and P-states in MP systems
+ // PDCx[4] = OS supports ind. C2/C3 in MP systems
+ //
+ If(And(PDC2,0x0018))
+ {
+ \_PR.CPU1.APCT()
+ }
+
+ Store (PDC2, PDC0)
+ Return()
+ }
+} // End CPU2
+
+Scope(\_PR.CPU3)
+{
+ Method(_PDC,1)
+ {
+ //
+ // Call the _PDC for CPU1.
+ //
+ Store(\_PR.CPU0.CPDC(Arg0), Local0)
+ GCAP(Local0)
+ Return (Local0)
+ }
+
+ Method(_OSC, 4)
+ {
+ //
+ // Call the _OSC for CPU1.
+ //
+ Store(\_PR.CPU0.COSC(Arg0, Arg1, Arg2, Arg3), Local0)
+ GCAP(Local0)
+ Return (Local0)
+ }
+
+ Method(GCAP,1)
+ {
+ // Point to Status DWORD in the Arg0 buffer (STATUS)
+ CreateDWordField(Arg0, 0, STS3)
+
+ // Point to Caps DWORDs of the Arg0 buffer (CAPABILITIES)
+ CreateDwordField(Arg0, 4, CAP3)
+
+ //
+ // If the UUID was unrecognized or the _OSC revision was unsupported,
+ // return without updating capabilities.
+ //
+ If(LOr(LEqual(STS3,0x6),LEqual(STS3,0xA)))
+ {
+ Return()
+ }
+
+ //
+ // Check if this is a query (BIT0 of Status = 1).
+ // If so, mask off the bits we support and return.
+ //
+ if (And(STS3, 1))
+ {
+ And(CAP3, 0xBFF, CAP3)
+ Return()
+ }
+
+ //
+ // Store result of PDC. (We clear out the MSB, which was just
+ // used as a placeholder for the compiler; and then "OR" the
+ // value in case we get multiple calls, each of which only
+ // reports partial support.)
+ //
+ Or(And(PDC3, 0x7FFFFFFF), CAP3, PDC3)
+ //
+ // Attempt to dynamically load the IST SSDTs if:
+ // (1) Driver supports P-States in MP configurations
+ // (2) Driver supports direct HW P-State control
+ //
+ // PDCx[3] = OS supports C1 and P-states in MP systems
+ // PDCx[0] = OS supports direct access of the perf MSR
+ //
+ If(LEqual(And(PDC3, 0x0009), 0x0009))
+ {
+ \_PR.CPU1.APPT()
+ }
+
+ //
+ // Load the CST SSDTs if:
+ // (1) Driver supports multi-processor configurations
+ //
+ // PDCx[3] = OS supports C1 and P-states in MP systems
+ // PDCx[4] = OS supports ind. C2/C3 in MP systems
+ //
+ If(And(PDC3,0x0018))
+ {
+ \_PR.CPU1.APCT()
+ }
+
+ Store (PDC3, PDC0)
+ Return()
+ }
+} // End CPU3
+
+Scope(\_PR.CPU4)
+{
+ Method(_PDC,1)
+ {
+ //
+ // Call the _PDC for CPU1.
+ //
+ Store(\_PR.CPU0.CPDC(Arg0), Local0)
+ GCAP(Local0)
+ Return (Local0)
+ }
+
+ Method(_OSC, 4)
+ {
+ //
+ // Call the _OSC for CPU1.
+ //
+ Store(\_PR.CPU0.COSC(Arg0, Arg1, Arg2, Arg3), Local0)
+ GCAP(Local0)
+ Return (Local0)
+ }
+
+ Method(GCAP,1)
+ {
+ // Point to Status DWORD in the Arg0 buffer (STATUS)
+ CreateDWordField(Arg0, 0, STS4)
+
+ // Point to Caps DWORDs of the Arg0 buffer (CAPABILITIES)
+ CreateDwordField(Arg0, 4, CAP4)
+
+ //
+ // If the UUID was unrecognized or the _OSC revision was unsupported,
+ // return without updating capabilities.
+ //
+ If(LOr(LEqual(STS4,0x6),LEqual(STS4,0xA)))
+ {
+ Return()
+ }
+
+ //
+ // Check if this is a query (BIT0 of Status = 1).
+ // If so, mask off the bits we support and return.
+ //
+ if (And(STS4, 1))
+ {
+ And(CAP4, 0xBFF, CAP4)
+ Return()
+ }
+
+ //
+ // Store result of PDC. (We clear out the MSB, which was just
+ // used as a placeholder for the compiler; and then "OR" the
+ // value in case we get multiple calls, each of which only
+ // reports partial support.)
+ //
+ Or(And(PDC4, 0x7FFFFFFF), CAP4, PDC4)
+ //
+ // Attempt to dynamically load the IST SSDTs if:
+ // (1) Driver supports P-States in MP configurations
+ // (2) Driver supports direct HW P-State control
+ //
+ // PDCx[3] = OS supports C1 and P-states in MP systems
+ // PDCx[0] = OS supports direct access of the perf MSR
+ //
+ If(LEqual(And(PDC4, 0x0009), 0x0009))
+ {
+ \_PR.CPU1.APPT()
+ }
+
+ //
+ // Load the CST SSDTs if:
+ // (1) Driver supports multi-processor configurations
+ //
+ // PDCx[3] = OS supports C1 and P-states in MP systems
+ // PDCx[4] = OS supports ind. C2/C3 in MP systems
+ //
+ If(And(PDC4,0x0018))
+ {
+ \_PR.CPU1.APCT()
+ }
+
+ Store (PDC4, PDC0)
+ Return()
+ }
+} // End CPU4
+
+Scope(\_PR.CPU5)
+{
+ Method(_PDC,1)
+ {
+ //
+ // Call the _PDC for CPU1.
+ //
+ Store(\_PR.CPU0.CPDC(Arg0), Local0)
+ GCAP(Local0)
+ Return (Local0)
+ }
+
+ Method(_OSC, 4)
+ {
+ //
+ // Call the _OSC for CPU1.
+ //
+ Store(\_PR.CPU0.COSC(Arg0, Arg1, Arg2, Arg3), Local0)
+ GCAP(Local0)
+ Return (Local0)
+ }
+
+ Method(GCAP,1)
+ {
+ // Point to Status DWORD in the Arg0 buffer (STATUS)
+ CreateDWordField(Arg0, 0, STS5)
+
+ // Point to Caps DWORDs of the Arg0 buffer (CAPABILITIES)
+ CreateDwordField(Arg0, 4, CAP5)
+
+ //
+ // If the UUID was unrecognized or the _OSC revision was unsupported,
+ // return without updating capabilities.
+ //
+ If(LOr(LEqual(STS5,0x6),LEqual(STS5,0xA)))
+ {
+ Return()
+ }
+
+ //
+ // Check if this is a query (BIT0 of Status = 1).
+ // If so, mask off the bits we support and return.
+ //
+ if (And(STS5, 1))
+ {
+ And(CAP5, 0xBFF, CAP5)
+ Return()
+ }
+
+ //
+ // Store result of PDC. (We clear out the MSB, which was just
+ // used as a placeholder for the compiler; and then "OR" the
+ // value in case we get multiple calls, each of which only
+ // reports partial support.)
+ //
+ Or(And(PDC5, 0x7FFFFFFF), CAP5, PDC5)
+ //
+ // Attempt to dynamically load the IST SSDTs if:
+ // (1) Driver supports P-States in MP configurations
+ // (2) Driver supports direct HW P-State control
+ //
+ // PDCx[3] = OS supports C1 and P-states in MP systems
+ // PDCx[0] = OS supports direct access of the perf MSR
+ //
+ If(LEqual(And(PDC5, 0x0009), 0x0009))
+ {
+ \_PR.CPU1.APPT()
+ }
+
+ //
+ // Load the CST SSDTs if:
+ // (1) Driver supports multi-processor configurations
+ //
+ // PDCx[3] = OS supports C1 and P-states in MP systems
+ // PDCx[4] = OS supports ind. C2/C3 in MP systems
+ //
+ If(And(PDC5,0x0018))
+ {
+ \_PR.CPU1.APCT()
+ }
+
+ Store (PDC5, PDC0)
+ Return()
+ }
+} // End CPU5
+
+Scope(\_PR.CPU6)
+{
+ Method(_PDC,1)
+ {
+ //
+ // Call the _PDC for CPU1.
+ //
+ Store(\_PR.CPU0.CPDC(Arg0), Local0)
+ GCAP(Local0)
+ Return (Local0)
+ }
+
+ Method(_OSC, 4)
+ {
+ //
+ // Call the _OSC for CPU1.
+ //
+ Store(\_PR.CPU0.COSC(Arg0, Arg1, Arg2, Arg3), Local0)
+ GCAP(Local0)
+ Return (Local0)
+ }
+
+ Method(GCAP,1)
+ {
+ // Point to Status DWORD in the Arg0 buffer (STATUS)
+ CreateDWordField(Arg0, 0, STS6)
+
+ // Point to Caps DWORDs of the Arg0 buffer (CAPABILITIES)
+ CreateDwordField(Arg0, 4, CAP6)
+
+ //
+ // If the UUID was unrecognized or the _OSC revision was unsupported,
+ // return without updating capabilities.
+ //
+ If(LOr(LEqual(STS6,0x6),LEqual(STS6,0xA)))
+ {
+ Return()
+ }
+
+ //
+ // Check if this is a query (BIT0 of Status = 1).
+ // If so, mask off the bits we support and return.
+ //
+ if (And(STS6, 1))
+ {
+ And(CAP6, 0xBFF, CAP6)
+ Return()
+ }
+
+ //
+ // Store result of PDC. (We clear out the MSB, which was just
+ // used as a placeholder for the compiler; and then "OR" the
+ // value in case we get multiple calls, each of which only
+ // reports partial support.)
+ //
+ Or(And(PDC6, 0x7FFFFFFF), CAP6, PDC6)
+ //
+ // Attempt to dynamically load the IST SSDTs if:
+ // (1) Driver supports P-States in MP configurations
+ // (2) Driver supports direct HW P-State control
+ //
+ // PDCx[3] = OS supports C1 and P-states in MP systems
+ // PDCx[0] = OS supports direct access of the perf MSR
+ //
+ If(LEqual(And(PDC6, 0x0009), 0x0009))
+ {
+ \_PR.CPU1.APPT()
+ }
+
+ //
+ // Load the CST SSDTs if:
+ // (1) Driver supports multi-processor configurations
+ //
+ // PDCx[3] = OS supports C1 and P-states in MP systems
+ // PDCx[4] = OS supports ind. C2/C3 in MP systems
+ //
+ If(And(PDC6,0x0018))
+ {
+ \_PR.CPU1.APCT()
+ }
+
+ Store (PDC6, PDC0)
+ Return()
+ }
+} // End CPU6
+
+Scope(\_PR.CPU7)
+{
+ Method(_PDC,1)
+ {
+ //
+ // Call the _PDC for CPU1.
+ //
+ Store(\_PR.CPU0.CPDC(Arg0), Local0)
+ GCAP(Local0)
+ Return (Local0)
+ }
+
+ Method(_OSC, 4)
+ {
+ //
+ // Call the _OSC for CPU1.
+ //
+ Store(\_PR.CPU0.COSC(Arg0, Arg1, Arg2, Arg3), Local0)
+ GCAP(Local0)
+ Return (Local0)
+ }
+
+ Method(GCAP,1)
+ {
+ // Point to Status DWORD in the Arg0 buffer (STATUS)
+ CreateDWordField(Arg0, 0, STS7)
+
+ // Point to Caps DWORDs of the Arg0 buffer (CAPABILITIES)
+ CreateDwordField(Arg0, 4, CAP7)
+
+ //
+ // If the UUID was unrecognized or the _OSC revision was unsupported,
+ // return without updating capabilities.
+ //
+ If(LOr(LEqual(STS7,0x6),LEqual(STS7,0xA)))
+ {
+ Return()
+ }
+
+ //
+ // Check if this is a query (BIT0 of Status = 1).
+ // If so, mask off the bits we support and return.
+ //
+ if (And(STS7, 1))
+ {
+ And(CAP7, 0xBFF, CAP7)
+ Return()
+ }
+
+ //
+ // Store result of PDC. (We clear out the MSB, which was just
+ // used as a placeholder for the compiler; and then "OR" the
+ // value in case we get multiple calls, each of which only
+ // reports partial support.)
+ //
+ Or(And(PDC7, 0x7FFFFFFF), CAP7, PDC7)
+ //
+ // Attempt to dynamically load the IST SSDTs if:
+ // (1) Driver supports P-States in MP configurations
+ // (2) Driver supports direct HW P-State control
+ //
+ // PDCx[3] = OS supports C1 and P-states in MP systems
+ // PDCx[0] = OS supports direct access of the perf MSR
+ //
+ If(LEqual(And(PDC7, 0x0009), 0x0009))
+ {
+ \_PR.CPU1.APPT()
+ }
+
+ //
+ // Load the CST SSDTs if:
+ // (1) Driver supports multi-processor configurations
+ //
+ // PDCx[3] = OS supports C1 and P-states in MP systems
+ // PDCx[4] = OS supports ind. C2/C3 in MP systems
+ //
+ If(And(PDC7,0x0018))
+ {
+ \_PR.CPU1.APCT()
+ }
+
+ Store (PDC7, PDC0)
+ Return()
+ }
+} // End CPU7
+} // End of Definition Block
diff --git a/ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/Ctdp.asl b/ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/Ctdp.asl
new file mode 100644
index 0000000..3ac992f
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/Ctdp.asl
@@ -0,0 +1,310 @@
+/*++
+ 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
+--*/
+
+/*++
+
+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.
+
+Module Name:
+
+ Ctdp.asl - Enable CTDP without using a driver or EC, i.e. this is the BIOS only solution.
+
+Abstract:
+
+ Intel Processor Power Management ACPI Code
+
+ WARNING: You are authorized and licensed to install and use this BIOS code
+ ONLY on an IST PC. This utility may damage any system that does not
+ meet these requirements.
+
+ An IST PC is a computer which
+ (1) Is capable of seamlessly and automatically transitioning among
+ multiple performance states (potentially operating at different
+ efficiency ratings) based upon power source changes, END user
+ preference, processor performance demand, and thermal conditions; and
+ (2) Includes an Intel Pentium II processors, Intel Pentium III
+ processor, Mobile Intel Pentium III Processor-M, Mobile Intel Pentium 4
+ Processor-M, Intel Pentium M Processor, or any other future Intel
+ processors that incorporates the capability to transition between
+ different performance states by altering some, or any combination of,
+ the following processor attributes: core voltage, core frequency, bus
+ frequency, number of processor cores available, or any other attribute
+ that changes the efficiency (instructions/unit time-power) at which the
+ processor operates.
+
+--*/
+
+DefinitionBlock (
+ "CTDP.aml",
+ "SSDT",
+ 0x01,
+ "CtdpB",
+ "CtdpB",
+ 0x1000
+ )
+{
+
+External(TCNT, IntObj)
+External(PNHM, IntObj)
+External(\_SB.PCI0, DeviceObj)
+External(\_SB.PCI0.MHBR, FieldUnitObj)
+External(\_PR.CPU0, DeviceObj)
+External(\_PR.CPU1, DeviceObj)
+External(\_PR.CPU2, DeviceObj)
+External(\_PR.CPU3, DeviceObj)
+External(\_PR.CPU4, DeviceObj)
+External(\_PR.CPU5, DeviceObj)
+External(\_PR.CPU6, DeviceObj)
+External(\_PR.CPU7, DeviceObj)
+External(\_PR.CPU0._PPC, IntObj)
+External(\_PR.CPU0._PSS, MethodObj)
+External(\_SB.PCCD.PENB, IntObj)
+
+Scope(\_SB.PCI0)
+{
+ //
+ // Memory window to the CTDP registers starting at MCHBAR+5000h.
+ //
+ OperationRegion (MBAR, SystemMemory, Add(ShiftLeft(MHBR,15),0x5000), 0x1000)
+ Field (MBAR, ByteAcc, NoLock, Preserve)
+ {
+ Offset (0x930), // PACKAGE_POWER_SKU (MCHBAR+0x5930)
+ PTDP, 15, // TDP Package Power [14:0]
+ , 1, // reserved [15]
+ PMIN, 15, // Minimal Package Power [30:16]
+ , 1, // Reserved [31]
+ PMAX, 15, // Maximal Package Power [46:32]
+ , 1, // Reserved [47]
+ TMAX, 7, // Maximal Time Window [54:48]
+ Offset (0x938), // PACKAGE_POWER_SKU_UNIT (MCHBAR+0x5938)
+ PWRU, 4, // Power Units [3:0]
+ , 4, // Reserved [7:4]
+ EGYU, 5, // Energy Units [12:8]
+ , 3, // Reserved [15:13]
+ TIMU, 4, // Time Units [19:16]
+ Offset (0x958), // PLATFORM_INFO (MCHBAR+0x5958)
+ , 32, // [31:0]
+ LPMS, 1, // LPM Support [32]
+ CTNL, 2, // CONFIG_TDP_NUM_LEVELS [34:33]
+ Offset (0x9A0), // TURBO_POWER_LIMIT1 (MCHBAR+0x59A0)
+ PPL1, 15, // PKG_PWR_LIM_1 [14:0]
+ PL1E,1, // PKG_PWR_LIM1_EN [15]
+ , 1, // reserved [16]
+ PL1T, 7, // PKG_PWR_LIM_1_TIME [23:17]
+ Offset (0x9A4), // TURBO_POWER_LIMIT2 (MCHBAR+0x59A4)
+ PPL2, 15, // PKG_PWR_LIM_2 [14:0]
+ PL2E,1, // PKG_PWR_LIM2_EN [15]
+ , 1, // reserved [16]
+ PL2T, 7, // PKG_PWR_LIM_2_TIME [23:17]
+ Offset (0xF3C), // CONFIG_TDP_NOMINAL (MCHBAR+0x5F3C)
+ TARN, 8, // TDP Ratio [7:0]
+ Offset (0xF40), // CONFIG_TDP_LEVEL1 (MCHBAR+0x5F40)
+ PTD1, 15, // Package TDP [14:0]
+ , 1, // reserved [15]
+ TAR1, 8, // TDP Ratio [23:16]
+ , 8, // reserved [31:24]
+ PMX1, 15, // Package MAX Power [46:32]
+ , 1, // reserved [47]
+ PMN1, 15, // Package MIN Power [62:48]
+ Offset (0xF48), // CONFIG_TDP_LEVEL2 (MCHBAR+0x5F48)
+ PTD2, 15, // Package TDP [14:0]
+ , 1, // reserved [15]
+ TAR2, 8, // TDP Ratio [23:16]
+ , 8, // reserved [31:24]
+ PMX2, 15, // Package MAX Power [46:32]
+ , 1, // reserved [47]
+ PMN2, 15, // Package MIN Power [62:48]
+ Offset (0xF50), // CONFIG_TDP_CONTROL (MCHBAR+0x5F50)
+ CTCL, 2, // TDP Level [1:0]
+ , 29, // reserved [30:2]
+ CLCK, 1, // Config TDP Lock [31]
+ Offset (0xF54), // TURBO_ACTIVATION_RATIO (MCHBAR+0x5F54)
+ TAR_, 8, // Max Non Turbo Ratio [7:0]
+ }
+
+ // CTCU (Config Tdp Control Up)
+ //
+ // Program the CTDP Up point.
+ //
+ // Arguments: (0)
+ // None
+ // Return Value:
+ // None
+ //
+ Method(CTCU)
+ {
+ Store(PTD2,PPL1) // Set PL1
+ Store(1,PL1E) // Set PL1 enable
+ Store(CLC2(PTD2),PPL2) // Set PL2
+ Store(1,PL2E) // Set PL2 enable
+ SPPC(1) // Set _PPC
+ Subtract(TAR2,1,TAR_) // Set TAR
+ Store(2,CTCL) // Set CTC
+ }
+
+ // CTCN (Config Tdp Control Nominal)
+ //
+ // Program the CTDP Nominal point.
+ //
+ // Arguments: (0)
+ // None
+ // Return Value:
+ // None
+ //
+ Method(CTCN)
+ {
+ If(LEqual(CTCL,1)) // algorithm for going to Nominal from Down
+ {
+ Store(PTDP,PPL1) // Set PL1
+ Store(1,PL1E) // Set PL1 enable
+ Store(CLC2(PTDP),PPL2) // Set PL2
+ Store(1,PL2E) // Set PL2 enable
+ NPPC(TARN) // Set _PPC
+ Subtract(TARN,1,TAR_) // Set TAR
+ Store(0,CTCL) // Set CTC
+ }
+ ElseIf(LEqual(CTCL,2)) // algorithm for going to Nominal from Up
+ {
+ Store(0,CTCL) // Set CTC
+ Subtract(TARN,1,TAR_) // Set TAR
+ NPPC(TARN) // Set _PPC
+ Store(CLC2(PTDP),PPL2) // Set PL2
+ Store(1,PL2E) // Set PL2 enable
+ Store(PTDP,PPL1) // Set PL1
+ Store(1,PL1E) // Set PL1 enable
+ }
+ }
+
+ // CTCD (Config Tdp Control Down)
+ //
+ // Program the CTDP Down point.
+ //
+ // Arguments: (0)
+ // None
+ // Return Value:
+ // None
+ //
+ Method(CTCD)
+ {
+ Store(1,CTCL) // Set CTC
+ Subtract(TAR1,1,TAR_) // Set TAR
+ NPPC(TAR1) // Set _PPC
+ Store(CLC2(PTD1),PPL2) // Set PL2
+ Store(1,PL2E) // Set PL2 enable
+ Store(PTD1,PPL1) // Set PL1
+ Store(1,PL1E) // Set PL1 enable
+ }
+
+ // NPPC (Notify _PPC object)
+ //
+ // Find the ratio or next highest ratio in the _PSS table and program _PPC with the index of that ratio.
+ //
+ // Arguments: (1)
+ // Arg0 - Turbo Activation Ratio
+ // Return Value:
+ // None
+ //
+ Method(NPPC,1)
+ {
+ Name(TRAT,0) // holder for the target ratio
+ Name(PRAT,0) // holder for the ratio in _PSS table
+ Name(TMPI,0) // index
+ Store(Arg0,TRAT) // init target ratio from caller
+ Store(SizeOf(\_PR.CPU0._PSS),TMPI) // init index from _PSS
+
+ While(LNotEqual(TMPI,0)){
+ Decrement(TMPI) // convert from 1 based count to 0 based count
+ Store(DeRefOf(Index(DeRefOf(Index(\_PR.CPU0._PSS, TMPI)),4)),PRAT)
+ ShiftRight(PRAT,8,PRAT)
+ If(LGreaterEqual(PRAT,TRAT)){
+ SPPC(TMPI)
+ Break
+ }
+ }
+ }
+
+ // SPPC (Set Participant Performance Capability)
+ //
+ // Progam the _PPC object and notify the OSPM.
+ //
+ // Arguments: (1)
+ // Arg0 - integer
+ // Return Value:
+ // None
+ //
+ Method(SPPC,1,Serialized)
+ {
+ Store(Arg0, \_PR.CPU0._PPC) // Note: CPU0._PPC is an Integer not a Method
+
+ If(CondRefOf(\_SB.PCCD.PENB)) { // is CPPC enabled in SETUP?
+ Notify(\_SB.PCCD,0x82) // CPPC notify
+ } Else {
+ Switch(ToInteger(TCNT)){
+ Case(8){
+ Notify(\_PR.CPU0, 0x80) // Tell CPU0 driver to re-eval _PPC
+ Notify(\_PR.CPU1, 0x80) // Tell CPU1 driver to re-eval _PPC
+ Notify(\_PR.CPU2, 0x80) // Tell CPU2 driver to re-eval _PPC
+ Notify(\_PR.CPU3, 0x80) // Tell CPU3 driver to re-eval _PPC
+ Notify(\_PR.CPU4, 0x80) // Tell CPU4 driver to re-eval _PPC
+ Notify(\_PR.CPU5, 0x80) // Tell CPU5 driver to re-eval _PPC
+ Notify(\_PR.CPU6, 0x80) // Tell CPU6 driver to re-eval _PPC
+ Notify(\_PR.CPU7, 0x80) // Tell CPU7 driver to re-eval _PPC
+ }
+ Case(4){
+ Notify(\_PR.CPU0, 0x80) // Tell CPU0 driver to re-eval _PPC
+ Notify(\_PR.CPU1, 0x80) // Tell CPU1 driver to re-eval _PPC
+ Notify(\_PR.CPU2, 0x80) // Tell CPU2 driver to re-eval _PPC
+ Notify(\_PR.CPU3, 0x80) // Tell CPU3 driver to re-eval _PPC
+ }
+ Case(2){
+ Notify(\_PR.CPU0, 0x80) // Tell CPU0 driver to re-eval _PPC
+ Notify(\_PR.CPU1, 0x80) // Tell CPU1 driver to re-eval _PPC
+ }
+ Default{
+ Notify(\_PR.CPU0, 0x80) // Tell CPU0 driver to re-eval _PPC
+ }
+ }
+ }
+ }
+
+ // CLC2 (CaLCulate PL2)
+ //
+ // IF Haswell Traditional THEN multiply PL1 by 1.25 to get PL2.
+ // ELSE IF Haswell ULT THEN use 25 watts as the PL2.
+ //
+ // Arguments: (1)
+ // Arg0 - integer
+ // Return Value:
+ // integer
+ //
+ Method(CLC2,1)
+ {
+ And(PNHM,0x0FFF0FF0,Local0) // remove stepping from CPUID
+ Switch(Local0){
+ Case(0x000306C0){ // Haswell Traditional
+ Return(Divide(Multiply(Arg0,5),4)) // Multiply a number by 1.25
+ }
+ Case(0x00040650){ // Haswell ULT
+ Return(Multiply(25,8))
+ }
+ Default{
+ Return(Divide(Multiply(Arg0,5),4)) // Multiply a number by 1.25
+ }
+ }
+ }
+
+} // end of scope(\_SB.PCI0)
+} // end of definition block
diff --git a/ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/LakeTiny.asl b/ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/LakeTiny.asl
new file mode 100644
index 0000000..1d2922c
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/AcpiTables/Ssdt/LakeTiny.asl
@@ -0,0 +1,157 @@
+/*++
+ 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
+--*/
+
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+ LakeTiny.asl
+
+Abstract:
+
+ Intel Processor Power Management ACPI Code - LakeTiny Support
+
+ WARNING: You are authorized and licensed to install and use this BIOS code
+ ONLY on an IST PC. This utility may damage any system that does not
+ meet these requirements.
+
+ An IST PC is a computer which
+ (1) Is capable of seamlessly and automatically transitioning among
+ multiple performance states (potentially operating at different
+ efficiency ratings) based upon power source changes, END user
+ preference, processor performance demand, and thermal conditions; and
+ (2) Includes an Intel Pentium II processors, Intel Pentium III
+ processor, Mobile Intel Pentium III Processor-M, Mobile Intel Pentium 4
+ Processor-M, Intel Pentium M Processor, or any other future Intel
+ processors that incorporates the capability to transition between
+ different performance states by altering some, or any combination of,
+ the following processor attributes: core voltage, core frequency, bus
+ frequency, number of processor cores available, or any other attribute
+ that changes the efficiency (instructions/unit time-power) at which the
+ processor operates.
+
+--*/
+
+
+DefinitionBlock (
+ "LakeTiny.aml",
+ "SSDT",
+ 1,
+ "PmRef",
+ "LakeTiny",
+ 0x3000
+ )
+{
+External(\_SB.PCI0.SAT0, DeviceObj)
+External(\_SB.PCI0.SAT1, DeviceObj)
+External(\PNOT, MethodObj)
+External(\_PR.CPU0.GEAR)
+External(MPMF) //Bit0: LakeTiny Support Enable/Disable
+
+Scope(\_SB.PCI0.SAT0) {
+ //
+ // Lake Tiny Performance Control Methods
+ //
+ Method(SLT1,0, Serialized)
+ {
+ If (CondRefOf(\_PR.CPU0.GEAR))
+ {
+ Store (0x00, \_PR.CPU0.GEAR) // Select Lake Tiny CST GEAR 1
+ \PNOT () // OS notification for _CST evaluation
+ }
+ Return(0)
+ }
+
+ Method(SLT2,0, Serialized)
+ {
+ If (CondRefOf(\_PR.CPU0.GEAR))
+ {
+ Store (0x01, \_PR.CPU0.GEAR) // Select Lake Tiny CST GEAR 2
+ \PNOT () // OS notification for _CST evaluation
+ }
+
+ Return(0)
+ }
+
+ Method(SLT3,0, Serialized)
+ {
+ If (CondRefOf(\_PR.CPU0.GEAR))
+ {
+ Store (0x02, \_PR.CPU0.GEAR) // Select Lake Tiny CST GEAR 3
+ \PNOT () // OS notification for _CST evaluation
+ }
+
+ Return(0)
+ }
+
+ Method(GLTS,0, Serialized)
+ {
+ Store(\_PR.CPU0.GEAR,local0)
+ ShiftLeft(local0,1,local0) // Bits 1:2 is Gear
+ Or(local0,0x01,local0) // Bit 0 enable/disable
+ Return(local0)
+ }
+}
+
+Scope(\_SB.PCI0.SAT1){
+ //
+ // Lake Tiny Performance Control Methods
+ //
+ Method(SLT1,0, Serialized)
+ {
+ If (CondRefOf(\_PR.CPU0.GEAR))
+ {
+ Store (0x00, \_PR.CPU0.GEAR) // Select Lake Tiny CST GEAR 1
+ \PNOT () // OS notification for _CST evaluation
+ }
+ Return(0)
+ }
+
+ Method(SLT2,0, Serialized)
+ {
+ If (CondRefOf(\_PR.CPU0.GEAR))
+ {
+ Store (0x01, \_PR.CPU0.GEAR) // Select Lake Tiny CST GEAR 2
+ \PNOT () // OS notification for _CST evaluation
+ }
+
+ Return(0)
+ }
+
+ Method(SLT3,0, Serialized)
+ {
+ If (CondRefOf(\_PR.CPU0.GEAR))
+ {
+ Store (0x02, \_PR.CPU0.GEAR) // Select Lake Tiny CST GEAR 3
+ \PNOT () // OS notification for _CST evaluation
+ }
+
+ Return(0)
+ }
+
+ Method(GLTS,0, Serialized)
+ {
+ Store(\_PR.CPU0.GEAR,local0)
+ ShiftLeft(local0,1,local0) // Bits 1:2 is Gear
+ And(MPMF,01,local1)
+ Or(local0,local1,local0) // Bit 0 enable/disable
+ Return(local0)
+ }
+}
+
+} // End of Definition Block
diff --git a/ReferenceCode/Haswell/PowerManagement/Dxe/IdleStates.c b/ReferenceCode/Haswell/PowerManagement/Dxe/IdleStates.c
new file mode 100644
index 0000000..a450b5d
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/Dxe/IdleStates.c
@@ -0,0 +1,918 @@
+/** @file
+ This file contains power management C State configuration functions for
+ Haswell processors.
+
+ Acronyms:
+ PPM - Processor Power Management
+ TM - Thermal Monitor
+ IST - Intel(R) Speedstep technology
+ HT - Hyper-Threading Technology
+
+@copyright
+ Copyright (c) 2012 - 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 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
+
+**/
+#include "PowerMgmtCommon.h"
+
+/**
+ Initializes C States Power management features
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+**/
+VOID
+InitializeCState (
+ IN POWER_MGMT_CONFIG *CpuPmConfig
+ )
+{
+ EFI_STATUS Status;
+ UINT16 mAcpiBaseAddr;
+ ///
+ /// Get the ACPI Base Address
+ ///
+ mAcpiBaseAddr = PchLpcPciCfg16 (R_PCH_LPC_ACPI_BASE) & 0xFFFE;
+
+ ///
+ /// Initialize C states, some are general, some are processor specific.
+ /// Dynamic loading of CST SSDT tables occurs at PpmPostInit.
+ ///
+ EnableCStates (mAcpiBaseAddr + PM_CST_LVL2);
+ ///
+ /// Calibrate C State 24MHz BCLK
+ ///
+//@todo: Need to finalize on whether or not re-calibration option should be provided
+ Status = CalibrateBclkForCStates ();
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((EFI_D_INFO, "24MHz BCLK calibration Failed \n"));
+//@todo: Need to finalize on how to handle failure of 24 MHz calibration
+ }
+
+ if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_C_STATES) {
+ ///
+ /// Update Fadt table for C State support.
+ ///
+ ConfigureFadtCStates ();
+ }
+ InitCstatePreWake (mCpuPmConfig);
+
+}
+
+/**
+ Disable/Enable the CState Pre-Wake Feature
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+**/
+VOID
+InitCstatePreWake (
+ IN POWER_MGMT_CONFIG *CpuPmConfig
+ )
+{
+ MSR_REGISTER TempMsr;
+
+ TempMsr.Qword = AsmReadMsr64 (MSR_POWER_CTL);
+ TempMsr.Dwords.Low &= ~(B_MSR_POWER_CTL_CSTATE_PRE_WAKE_DISABLE);
+ if (CpuPmConfig->pFunctionEnables->CStatePreWake == PPM_DISABLE) {
+ TempMsr.Dwords.Low |= B_MSR_POWER_CTL_CSTATE_PRE_WAKE_DISABLE;
+ }
+ AsmWriteMsr64 (MSR_POWER_CTL, TempMsr.Qword);
+
+ return;
+}
+
+/**
+ Enables C-State support as specified by the input flags on all logical
+ processors and sets associated timing requirements in the chipset.
+
+ @param[in] C3IoAddress IO address to generate C3 states (PM base + 014 usually)
+**/
+VOID
+EnableCStates (
+ IN UINT16 C3IoAddress
+ )
+{
+ MSR_REGISTER PowerCtl;
+ MSR_REGISTER TempMsr;
+ UINT32 LCR0Latency;
+ UINT32 LCR1Latency;
+ UINT32 LCR2Latency;
+ UINT32 LCR3Latency;
+ UINT32 LCR4Latency;
+ UINT32 LCR5Latency;
+ UINT16 EnableCStateParameters;
+ CPU_FAMILY mCpuFamilyId;
+
+ mCpuFamilyId = mPpmGlobalNvsAreaProtocol->Area->Cpuid & CPUID_FULL_FAMILY_MODEL;
+ ///
+ /// Load the C-State parameters to pass to the core function.
+ ///
+ EnableCStateParameters = C3IoAddress;
+ ///
+ /// Enable C-States on all logical processors.
+ ///
+ RunOnAllLogicalProcessors (ApSafeEnableCStates, &EnableCStateParameters);
+ ///
+ /// If C-states are disabled or not supported, Disable C1e and retrun
+ ///
+ if ((mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_C_STATES) == 0) {
+ PowerCtl.Qword = AsmReadMsr64 (MSR_POWER_CTL);
+ PowerCtl.Dwords.Low &= ~B_MSR_POWER_CTL_C1E;
+ AsmWriteMsr64 (MSR_POWER_CTL, PowerCtl.Qword);
+ DEBUG (
+ (EFI_D_INFO,
+ "Setup C state disabled.Disable C1e. MSR(1FC) : %X %X\n",
+ PowerCtl.Dwords.High,
+ PowerCtl.Dwords.Low)
+ );
+ return;
+ }
+ ///
+ /// Configure supported enhanced C-states
+ ///
+ /// Read Power Ctl MSR
+ ///
+ PowerCtl.Qword = AsmReadMsr64 (MSR_POWER_CTL);
+ DEBUG ((EFI_D_INFO, "MSR(1FC) before configuring C1E: %X %X\n", PowerCtl.Dwords.High, PowerCtl.Dwords.Low));
+ ///
+ /// Enable supported states
+ ///
+ if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_C1E) {
+ PowerCtl.Dwords.Low |= B_MSR_POWER_CTL_C1E;
+ } else {
+ PowerCtl.Dwords.Low &= ~B_MSR_POWER_CTL_C1E;
+ }
+ ///
+ /// Update Power Control MSR
+ ///
+ AsmWriteMsr64 (MSR_POWER_CTL, PowerCtl.Qword);
+ DEBUG ((EFI_D_INFO, "MSR(1FC) after configuring C1E: %X %X\n", PowerCtl.Dwords.High, PowerCtl.Dwords.Low));
+ ///
+ /// Program Interrupt response time limits used by processor to decided when to get into
+ /// package C3, C6 and C7
+ ///
+ DEBUG ((EFI_D_INFO, "Programming the 0xC3/C6/C7 (MSR 0x60A, 0x60B ,0X60C Latencies \n"));
+ //
+ // Package C3 Interrupt response time
+ //
+ TempMsr.Qword = AsmReadMsr64 (MSR_C_STATE_LATENCY_CONTROL_0);
+ DEBUG ((EFI_D_INFO, "MSR(60A) before configuring Latency: %X %X\n", TempMsr.Dwords.High, TempMsr.Dwords.Low));
+ TempMsr.Dwords.Low &= ~(B_INTERRUPT_RESPONSE_TIME_LIMIT_MASK | B_TIME_UNIT_MASK | B_PKG_IRTL_VALID);
+ ///
+ /// Program Interrupt Response Time Unit and Latency for MSR 0x60A
+ ///
+ TempMsr.Dwords.Low |= mCpuPmConfig->CstateLatencyControl0Irtl;
+ TempMsr.Dwords.Low |= LShiftU64 (mCpuPmConfig->CstateLatencyControl0TimeUnit, N_TIME_UNIT_OFFSET);
+ TempMsr.Dwords.Low |= B_PKG_IRTL_VALID;
+ AsmWriteMsr64 (MSR_C_STATE_LATENCY_CONTROL_0, TempMsr.Qword);
+ //
+ // Package C6/C7 short Interrupt response time
+ //
+ TempMsr.Qword = AsmReadMsr64 (MSR_C_STATE_LATENCY_CONTROL_1);
+ DEBUG ((EFI_D_INFO, "MSR(60B) before configuring Latency: %X %X\n", TempMsr.Dwords.High, TempMsr.Dwords.Low));
+ TempMsr.Dwords.Low &= ~(B_INTERRUPT_RESPONSE_TIME_LIMIT_MASK | B_TIME_UNIT_MASK | B_PKG_IRTL_VALID);
+ ///
+ /// Program Interrupt Response Time Unit and Latency for MSR 0x60B
+ ///
+ TempMsr.Dwords.Low |= mCpuPmConfig->CstateLatencyControl1Irtl;
+ TempMsr.Dwords.Low |= LShiftU64 (mCpuPmConfig->CstateLatencyControl1TimeUnit, N_TIME_UNIT_OFFSET);
+ TempMsr.Dwords.Low |= B_PKG_IRTL_VALID;
+ AsmWriteMsr64 (MSR_C_STATE_LATENCY_CONTROL_1, TempMsr.Qword);
+ //
+ // Package C6/C7 long Interrupt response time
+ //
+ TempMsr.Qword = AsmReadMsr64 (MSR_C_STATE_LATENCY_CONTROL_2);
+ DEBUG ((EFI_D_INFO, "MSR(60C) before configuring Latency: %X %X\n", TempMsr.Dwords.High, TempMsr.Dwords.Low));
+ TempMsr.Dwords.Low &= ~(B_INTERRUPT_RESPONSE_TIME_LIMIT_MASK | B_TIME_UNIT_MASK | B_PKG_IRTL_VALID);
+ ///
+ /// Program Interrupt Response Time Unit and Latency for MSR 0x60C
+ ///
+ TempMsr.Dwords.Low |= mCpuPmConfig->CstateLatencyControl2Irtl;
+ TempMsr.Dwords.Low |= LShiftU64 (mCpuPmConfig->CstateLatencyControl2TimeUnit, N_TIME_UNIT_OFFSET);
+ TempMsr.Dwords.Low |= B_PKG_IRTL_VALID;
+ AsmWriteMsr64 (MSR_C_STATE_LATENCY_CONTROL_2, TempMsr.Qword);
+ if (mCpuFamilyId == EnumCpuHswUlt) {
+ //
+ // Package C8 Interrupt response time
+ //
+ TempMsr.Qword = AsmReadMsr64 (MSR_C_STATE_LATENCY_CONTROL_3);
+ DEBUG ((EFI_D_INFO, "MSR(633) before configuring Latency: %X %X\n", TempMsr.Dwords.High, TempMsr.Dwords.Low));
+ TempMsr.Dwords.Low &= ~(B_INTERRUPT_RESPONSE_TIME_LIMIT_MASK | B_TIME_UNIT_MASK | B_PKG_IRTL_VALID);
+ ///
+ /// Program Interrupt Response Time Unit and Latency for MSR 0x633
+ ///
+ TempMsr.Dwords.Low |= mCpuPmConfig->CstateLatencyControl3Irtl;
+ TempMsr.Dwords.Low |= LShiftU64 (mCpuPmConfig->CstateLatencyControl3TimeUnit, N_TIME_UNIT_OFFSET);
+ TempMsr.Dwords.Low |= B_PKG_IRTL_VALID;
+ AsmWriteMsr64 (MSR_C_STATE_LATENCY_CONTROL_3, TempMsr.Qword);
+ //
+ // Package C9 Interrupt response time
+ //
+ TempMsr.Qword = AsmReadMsr64 (MSR_C_STATE_LATENCY_CONTROL_4);
+ DEBUG ((EFI_D_INFO, "MSR(634) before configuring Latency: %X %X\n", TempMsr.Dwords.High, TempMsr.Dwords.Low));
+ TempMsr.Dwords.Low &= ~(B_INTERRUPT_RESPONSE_TIME_LIMIT_MASK | B_TIME_UNIT_MASK | B_PKG_IRTL_VALID);
+ ///
+ /// Program Interrupt Response Time Unit and Latency for MSR 0x634
+ ///
+ TempMsr.Dwords.Low |= mCpuPmConfig->CstateLatencyControl4Irtl;
+ TempMsr.Dwords.Low |= LShiftU64 (mCpuPmConfig->CstateLatencyControl4TimeUnit, N_TIME_UNIT_OFFSET);
+ TempMsr.Dwords.Low |= B_PKG_IRTL_VALID;
+ AsmWriteMsr64 (MSR_C_STATE_LATENCY_CONTROL_4, TempMsr.Qword);
+ //
+ // Package C10 Interrupt response time
+ //
+ TempMsr.Qword = AsmReadMsr64 (MSR_C_STATE_LATENCY_CONTROL_5);
+ DEBUG ((EFI_D_INFO, "MSR(635) before configuring Latency: %X %X\n", TempMsr.Dwords.High, TempMsr.Dwords.Low));
+ TempMsr.Dwords.Low &= ~(B_INTERRUPT_RESPONSE_TIME_LIMIT_MASK | B_TIME_UNIT_MASK | B_PKG_IRTL_VALID);
+ ///
+ /// Program Interrupt Response Time Unit and Latency for MSR 0x635
+ ///
+ TempMsr.Dwords.Low |= mCpuPmConfig->CstateLatencyControl5Irtl;
+ TempMsr.Dwords.Low |= LShiftU64 (mCpuPmConfig->CstateLatencyControl5TimeUnit, N_TIME_UNIT_OFFSET);
+ TempMsr.Dwords.Low |= B_PKG_IRTL_VALID;
+ AsmWriteMsr64 (MSR_C_STATE_LATENCY_CONTROL_5, TempMsr.Qword);
+ }
+ ///
+ /// Update the PPM Global NVS Area
+ ///
+ LCR0Latency = (1 << (mCpuPmConfig->CstateLatencyControl0TimeUnit * 5));
+ LCR0Latency = (LCR0Latency * mCpuPmConfig->CstateLatencyControl0Irtl) / 1000;
+ //
+ // _CST Latency: WordConst, so limit the latency value to max 0xFFFF
+ //
+ if (LCR0Latency > 0xFFFF) {
+ LCR0Latency = 0xFFFF;
+ }
+ LCR1Latency = (1 << (mCpuPmConfig->CstateLatencyControl1TimeUnit * 5));
+ LCR1Latency = (LCR1Latency * mCpuPmConfig->CstateLatencyControl1Irtl) / 1000;
+ if (LCR1Latency > 0xFFFF) {
+ LCR1Latency = 0xFFFF;
+ }
+ LCR2Latency = (1 << (mCpuPmConfig->CstateLatencyControl2TimeUnit * 5));
+ LCR2Latency = (LCR2Latency * mCpuPmConfig->CstateLatencyControl2Irtl) / 1000;
+ if (LCR2Latency > 0xFFFF) {
+ LCR2Latency = 0xFFFF;
+ }
+
+ LCR3Latency = (1 << (mCpuPmConfig->CstateLatencyControl3TimeUnit * 5));
+ LCR3Latency = (LCR3Latency * mCpuPmConfig->CstateLatencyControl3Irtl) / 1000;
+ if (LCR3Latency > 0xFFFF) {
+ LCR3Latency = 0xFFFF;
+ }
+
+ LCR4Latency = (1 << (mCpuPmConfig->CstateLatencyControl4TimeUnit * 5));
+ LCR4Latency = (LCR4Latency * mCpuPmConfig->CstateLatencyControl4Irtl) / 1000;
+ if (LCR4Latency > 0xFFFF) {
+ LCR4Latency = 0xFFFF;
+ }
+
+ LCR5Latency = (1 << (mCpuPmConfig->CstateLatencyControl5TimeUnit * 5));
+ LCR5Latency = (LCR5Latency * mCpuPmConfig->CstateLatencyControl5Irtl) / 1000;
+ if (LCR5Latency > 0xFFFF) {
+ LCR5Latency = 0xFFFF;
+ }
+
+ ///
+ /// Update the PPM Global NVS Area.
+ /// Update the PPM NVRAM values for C3
+ ///
+ mPpmGlobalNvsAreaProtocol->Area->C3MwaitValue = 0x10;
+ mPpmGlobalNvsAreaProtocol->Area->C3Latency = (UINT16) LCR0Latency;
+ ///
+ /// Update PPM NVRAM Values for C6
+ ///
+ if ((mCpuPmConfig->pFunctionEnables->LongLatencyC6) &&( mPpmGlobalNvsAreaProtocol->Area->PpmFlags & C6_LONG_LATENCY_ENABLE)) {
+ mPpmGlobalNvsAreaProtocol->Area->C6MwaitValue = 0x21;
+ mPpmGlobalNvsAreaProtocol->Area->C6Latency = (UINT16) LCR2Latency;
+ } else {
+ mPpmGlobalNvsAreaProtocol->Area->C6MwaitValue = 0x20;
+ mPpmGlobalNvsAreaProtocol->Area->C6Latency = (UINT16) LCR1Latency;
+ }
+ ///
+ /// Update PPM NVRAM Values for C7 - select the C-state supported among- C7 / C7S
+ ///
+ if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_C7) { // Is C7 supported ?
+ if ((mCpuPmConfig->pFunctionEnables->LongLatencyC7) && (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & C7_LONG_LATENCY_ENABLE)) {
+ mPpmGlobalNvsAreaProtocol->Area->C7MwaitValue = 0x31;
+ mPpmGlobalNvsAreaProtocol->Area->C7Latency = (UINT16) LCR2Latency;
+ } else {
+ mPpmGlobalNvsAreaProtocol->Area->C7MwaitValue = 0x30;
+ mPpmGlobalNvsAreaProtocol->Area->C7Latency = (UINT16) LCR1Latency;
+ }
+ }
+ if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_C7S) { // Is C7S supported ?
+ if ((mCpuPmConfig->pFunctionEnables->LongLatencyC7) && (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & C7s_LONG_LATENCY_ENABLE)) {
+ mPpmGlobalNvsAreaProtocol->Area->C7MwaitValue = 0x33;
+ mPpmGlobalNvsAreaProtocol->Area->C7Latency = (UINT16) LCR2Latency;
+ } else {
+ mPpmGlobalNvsAreaProtocol->Area->C7MwaitValue = 0x32;
+ mPpmGlobalNvsAreaProtocol->Area->C7Latency = (UINT16) LCR1Latency;
+ }
+ }
+ ///
+ /// Update PPM NVRAM Values for CD - select the deepest C-state supported among- C8 / C9 / C10
+ ///
+ if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_C10) { // C10 supported
+ mPpmGlobalNvsAreaProtocol->Area->CDIOLevel = PCH_ACPI_LV7;
+ mPpmGlobalNvsAreaProtocol->Area->CDPowerValue = C10_POWER;
+ mPpmGlobalNvsAreaProtocol->Area->CDMwaitValue = 0x60;
+ mPpmGlobalNvsAreaProtocol->Area->CDLatency = (UINT16) LCR5Latency;
+ } else if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_C9) { // C9 supported
+ mPpmGlobalNvsAreaProtocol->Area->CDIOLevel = PCH_ACPI_LV6;
+ mPpmGlobalNvsAreaProtocol->Area->CDPowerValue = C9_POWER;
+ mPpmGlobalNvsAreaProtocol->Area->CDMwaitValue = 0x50;
+ mPpmGlobalNvsAreaProtocol->Area->CDLatency = (UINT16) LCR4Latency;
+ } else if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_C8) { // C8 supported
+ mPpmGlobalNvsAreaProtocol->Area->CDIOLevel = PCH_ACPI_LV5;
+ mPpmGlobalNvsAreaProtocol->Area->CDPowerValue = C8_POWER;
+ mPpmGlobalNvsAreaProtocol->Area->CDMwaitValue = 0x40;
+ mPpmGlobalNvsAreaProtocol->Area->CDLatency = (UINT16) LCR3Latency;
+ }
+
+ return;
+}
+
+/**
+ BootScript for PCode Mailbox function for mailbox write commands.
+ This function will poll the mailbox interface for control, issue the command
+ during s3 resume
+
+ @param[IN] MailboxCommand,
+ @param[IN] MailboxData,
+**/
+VOID
+MailboxS3Write (
+ IN UINT32 MailboxCommand,
+ IN UINT32 MailboxData
+ )
+{
+#ifdef ULT_FLAG
+ UINT32 Data32Mask;
+ UINT32 Data32Value;
+ UINT16 StallCount;
+ UINT32 MchBar;
+
+ StallCount = 0;
+
+ ///
+ /// Poll the run/busy to ensure the interface is available
+ ///
+ Data32Mask = BIT31;
+ Data32Value = 0;
+ MchBar = (MmioRead32 (MmPciAddress (0, 0, 0, 0, MCHBAR_OFFSET)) &~BIT0);
+ SCRIPT_MEM_POLL (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (MchBar + PCODE_MAILBOX_INTERFACE_OFFSET),
+ &Data32Mask,
+ &Data32Value,
+ MAILBOX_WAIT_STALL,
+ MAILBOX_WAIT_TIMEOUT
+ );
+
+ ///
+ /// Write the PCODE mailbox DATA field
+ ///
+ MchBar = (MmioRead32 (MmPciAddress (0, 0, 0, 0, MCHBAR_OFFSET)) &~BIT0);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) ((MchBar + PCODE_MAILBOX_DATA_OFFSET)),
+ 1,
+ &(MailboxData)
+ );
+ ///
+ /// Write the PCODE mailbox Command field
+ ///
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (MchBar + PCODE_MAILBOX_INTERFACE_OFFSET),
+ 1,
+ &(MailboxCommand)
+ );
+#endif // ULT_FLAG
+ return;
+}
+
+/**
+ Calibrate 24MHz BCLK support to reduce the power consumption in idle states.
+
+ @retval EFI_UNSUPPORTED Unrecognized 24MHz BCLK Calibration Type.
+ @retval EFI_SUCCESS Processor C-State 24MHz BCLK support calibrated successfully.
+**/
+EFI_STATUS
+CalibrateBclkForCStates (
+ VOID
+ )
+{
+ /*****************************************************************************************************************
+ - BIOS can choose to configure the conversion factor or allow PCODE to calibrate itself or have NO calibration at all.
+ - If NO Calibration then the below steps are needed
+ o BIOS should bypass all calibration process and write a constant value via "WRITE convert ratio"
+ - If BIOS chooses PCODE calibration then the below steps are needed
+ o BIOS writes FSM interval: A value of all Fs is recommended for this
+ o Read PCODE calibration factor
+ o Store and use if needed on next Power up for BIOS calibration
+ - If BIOS chooses to calibrate itself then the below steps are needed
+ o Send command for calibration to prevent BCLK shut off
+ o Read TSC counter values (send command for atomic sampling of TSC100 and TSC24, then read the values)
+ o Delay (what is the maximum tolerable delay?)
+ o Read counters again
+ o Divide 100 MHz ticks by 24 MHz ticks to get the calibration factor
+ o Store the calibration factor value
+ o Write calibration factor using mailbox command during subsequent power-ups
+
+ Command: Command Name: Description:
+ 0x80000009 WriteTsc24_100Cmd Sample 24 MHz and 100 MHz TSC simultaneously
+ 0x80000109 ReadTsc24LowerCmd Read lower 32 bits of 24 MHz TSC
+ 0x80000209 ReadTsc24UpperCmd Read upper 32 bits of 24 MHz TSC
+ 0x80000309 ReadTsc100LowerCmd Read lower 32 bits of 100 MHz TSC
+ 0x80000409 ReadTsc100UpperCmd Read upper 32 bits of 100 MHz TSC
+ 0x80000509 ReadPcodeCalibratedCmd Read PCODE calibrated conversion factor
+ 0x80000609 WriteConversionRatioCmd Command for writing the conversion ratio
+ 0x80000709 WritePreventBclkOffCmd Command for calibration prevents BCLK from shutting off and prevents package
+ from entering deep C states
+ 0x80000809 WRITE_MEASURE_INTERVAL_CMD Measurement interval for pCode calibration of TSC24-to-TSC100 conversion factor
+ 0x80000909 WriteFsmMeasureIntvlCmd Write FSM measure interval
+ 0x85000000 StartCalValue Constant value to start calibration
+ 0xFFFFFFFF PcodeIntervalValue PCODE flow calibration time value
+
+ ***************************************************************************************************************/
+
+ EFI_STATUS Status = EFI_SUCCESS;
+
+#ifdef ULT_FLAG
+ CPU_FAMILY mCpuFamilyId;
+ mCpuFamilyId = mPpmGlobalNvsAreaProtocol->Area->Cpuid & CPUID_FULL_FAMILY_MODEL;
+ if (mCpuFamilyId == EnumCpuHswUlt) {
+ UINT32 PcodeIntervalValue;
+ UINT32 BiosMeasureIntervalValue;
+ UINT32 PcalFactor_Lower;
+ UINT32 PcalFactor_Upper;
+ UINT32 LibStatus;
+ UINT64 Tsc24_64;
+ UINT64 Tsc100_64;
+ UINT64 Temp24_64;
+ UINT64 Temp100_64;
+ UINT64 PcalFactor;
+ UINT64 SafeCalibrationValue;
+ UINT64 TscRemainder;
+
+ PCODE_BCLK_CALIBRATION_MAILBOX ReturnCalVal;
+
+ PcodeIntervalValue = 0xFFFFFFFF;
+ BiosMeasureIntervalValue = 0x7270E00;
+ PcalFactor_Lower = 0x0;
+ PcalFactor_Upper = 0x0;
+ Tsc24_64 = 0x0;
+ Tsc100_64 = 0x0;
+ Temp24_64 = 0x0;
+ Temp100_64 = 0x0;
+ PcalFactor = 0x0;
+ SafeCalibrationValue = 0x0;
+ TscRemainder = 0x0;
+ LibStatus = 0x0;
+ DEBUG ((EFI_D_INFO, "Initializing 24MHz BCLK calibration \n"));
+
+ switch (mCpuPmConfig->PcodeCalibration) {
+ case NO_CALIBRATE:
+ ///
+ /// Bypass all calibration process
+ ///
+ DEBUG ((EFI_D_INFO, "Bypass the 24MHz BCLK calibration \n"));
+ ///
+ /// Write a constant value
+ ///
+ Status = MailboxWrite(MAILBOX_TYPE_PCODE, WRITE_CONVERTION_RATIO_CMD, START_CAL_VALUE, &LibStatus);
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "24 MHz BCLK Calibration: Failed to write a constant value \n"));
+ break;
+ }
+ MailboxS3Write(WRITE_CONVERTION_RATIO_CMD, START_CAL_VALUE);
+ break;
+
+ case PCODE_CALIBRATE:
+ ///
+ /// Initiate the PCODE calibration
+ ///
+ DEBUG ((EFI_D_INFO, "Initiate PCODE 24MHz BCLK calibration \n"));
+ ///
+ /// BIOS writes FSM interval: A value of all F's is recommended for this
+ ///
+ Status = MailboxWrite(MAILBOX_TYPE_PCODE, WRITE_FSM_MEASURE_INTVL_CMD, PcodeIntervalValue, &LibStatus);
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "24 MHz BCLK Calibration: Failed BIOS writes FSM interval \n"));
+ break;
+ }
+ MailboxS3Write(WRITE_FSM_MEASURE_INTVL_CMD, PcodeIntervalValue);
+ break;
+
+ case BIOS_CALIBRATE:
+ ///
+ /// Initiate Bios calibration
+ ///
+ DEBUG ((EFI_D_INFO, "Initiate BIOS 24MHz BCLK calibration \n"));
+ ///
+ /// Send command for calibration to prevent BCLK shut off
+ ///
+ Status = MailboxWrite(MAILBOX_TYPE_PCODE, WRITE_PREVENT_BCLKOFF_CMD, 1, &LibStatus);
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "24 MHz BCLK Calibration: Failed Send command for calibration to prevent BCLK shut off \n"));
+ break;
+ }
+ ///
+ /// Read TSC counter values (send command for atomic sampling of TSC100 and TSC24)
+ ///
+ Status = MailboxWrite(MAILBOX_TYPE_PCODE, SAMPLE_TSC_24AND100_CMD, 0, &LibStatus);
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "24 MHz BCLK Calibration: Failed First Write TSC counter values (send command for atomic sampling of TSC100 and TSC24) \n"));
+ break;
+ }
+ Status = MailboxRead(MAILBOX_TYPE_PCODE, READ_TSC24_LOWER_CMD, &ReturnCalVal.TSC24_L1, &LibStatus);
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "24 MHz BCLK Calibration: Failed First read TSC-24 Lower 32 bits \n"));
+ break;
+ }
+ Status = MailboxRead(MAILBOX_TYPE_PCODE, READ_TSC24_UPPER_CMD, &ReturnCalVal.TSC24_U1, &LibStatus);
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "24 MHz BCLK Calibration: Failed First read TSC-24 Upper 32 bits \n"));
+ break;
+ }
+ Status = MailboxRead(MAILBOX_TYPE_PCODE, READ_TSC100_LOWER_CMD, &ReturnCalVal.TSC100_L1, &LibStatus);
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "24 MHz BCLK Calibration: Failed First read TSC-100 Lower 32 bits \n"));
+ break;
+ }
+ Status = MailboxRead(MAILBOX_TYPE_PCODE, READ_TSC100_UPPER_CMD, &ReturnCalVal.TSC100_U1, &LibStatus);
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "24 MHz BCLK Calibration: Failed First read TSC-100 Upper 32 bits \n"));
+ break;
+ }
+ ///
+ /// Store initial clock values
+ ///
+ Tsc24_64 = ((UINT64)ReturnCalVal.TSC24_U1 << 32);
+ Temp24_64 = (Tsc24_64 |= (ReturnCalVal.TSC24_L1));
+ Tsc100_64 = ((UINT64)ReturnCalVal.TSC100_U1 << 32);
+ Temp100_64 = (Tsc100_64 |= (ReturnCalVal.TSC100_L1));
+
+ ///
+ /// Delay for 22 ms
+ ///
+ gBS->Stall (PCODE_BCLK_CALIBRATION_TIMEOUT * STALL_ONE_MILLI_SECOND);
+
+ ///
+ /// Read TSC 24 and TSC 100 counters again, and calculate calibration factor
+ ///
+ Status = MailboxWrite(MAILBOX_TYPE_PCODE, SAMPLE_TSC_24AND100_CMD, 0, &LibStatus);
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "24 MHz BCLK Calibration: Failed Second Write TSC counter values (send command for atomic sampling of TSC100 and TSC24) \n"));
+ break;
+ }
+ Status = MailboxRead(MAILBOX_TYPE_PCODE, READ_TSC24_LOWER_CMD, &ReturnCalVal.TSC24_L2, &LibStatus);
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "24 MHz BCLK Calibration: Failed Second read TSC-24 Lower 32 bits \n"));
+ break;
+ }
+ Status = MailboxRead(MAILBOX_TYPE_PCODE, READ_TSC24_UPPER_CMD, &ReturnCalVal.TSC24_U2, &LibStatus);
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "24 MHz BCLK Calibration: Failed Second read TSC-24 Upper 32 bits \n"));
+ break;
+ }
+ Status = MailboxRead(MAILBOX_TYPE_PCODE, READ_TSC100_LOWER_CMD, &ReturnCalVal.TSC100_L2, &LibStatus);
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "24 MHz BCLK Calibration: Failed Second read TSC-100 Lower 32 bits \n"));
+ break;
+ }
+ Status = MailboxRead(MAILBOX_TYPE_PCODE, READ_TSC100_UPPER_CMD, &ReturnCalVal.TSC100_U2, &LibStatus);
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "24 MHz BCLK Calibration: Second read TSC-100 Upper 32 bits \n"));
+ break;
+ }
+ ///
+ /// Store current clock values, and calculate difference
+ ///
+ Tsc24_64 = ((UINT64)ReturnCalVal.TSC24_U2 << 32);
+ Tsc24_64 = ((Tsc24_64 |= (ReturnCalVal.TSC24_L2)) - Temp24_64);
+ Tsc100_64 = ((UINT64)ReturnCalVal.TSC100_U2 << 32);
+ Tsc100_64 = ((Tsc100_64 |= (ReturnCalVal.TSC100_L2)) - Temp100_64);
+
+ ///
+ /// Calculate updated conversion factor in fixed point format (U32.3.29)
+ ///
+ Tsc100_64 = (Tsc100_64 << 29);
+ if (Tsc24_64 !=0) {
+ PcalFactor = InternalMathDivRemS64x64 (Tsc100_64, Tsc24_64, (INT64 *) &TscRemainder);
+ }
+
+ ///
+ /// Read the TSC24-to-TSC100 conversion factor currently in use by pCode
+ ///
+ Status = MailboxRead(MAILBOX_TYPE_PCODE, READ_PCODE_CALIBRATED_CMD, &ReturnCalVal.PCalFactor, &LibStatus);
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "24 MHz BCLK Calibration: Failed read TSC24-to-TSC100 PCalFactor from pCode currently\n"));
+ break;
+ }
+
+ if (PcalFactor <= 0) {
+ ///
+ /// Set Safe Calibration Value as ReturnCalVal.PCalFactor which is TSC24-to-TSC100 PCalFactor read from pCode by READ_PCODE_CALIBRATED_CMD
+ ///
+ PcalFactor = ReturnCalVal.PCalFactor;
+ DEBUG ((EFI_D_ERROR, "24 MHz BCLK Calibration: Warning - SafeCalibrationValue used \n"));
+ }
+ PcalFactor_Lower |= PcalFactor;
+ PcalFactor_Upper |= (PcalFactor >> 32);
+ ///
+ /// Calibrate 24MHz BCLK using the calculated calibration factor value
+ ///
+ Status = MailboxWrite(MAILBOX_TYPE_PCODE, WRITE_CONVERTION_RATIO_CMD, PcalFactor_Lower, &LibStatus);
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "24 MHz BCLK Calibration: Failed Calibrate 24MHz BCLK using the calculated lower calibration factor value \n"));
+ break;
+ }
+ MailboxS3Write(WRITE_CONVERTION_RATIO_CMD, PcalFactor_Lower);
+
+ ///
+ /// Send command for calibration to turn BCLK on
+ ///
+ Status = MailboxWrite(MAILBOX_TYPE_PCODE, WRITE_PREVENT_BCLKOFF_CMD, 0, &LibStatus);
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "24 MHz BCLK Calibration: Failed Send command for calibration to turn BCLK on \n"));
+ break;
+ }
+ MailboxS3Write(WRITE_PREVENT_BCLKOFF_CMD, 0);
+
+ ///
+ /// Write measurement interval for pCode calibration of TSC24-to-TSC100 conversion factor
+ ///
+ Status = MailboxWrite(MAILBOX_TYPE_PCODE, WRITE_MEASURE_INTERVAL_CMD, BiosMeasureIntervalValue, &LibStatus);
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "24 MHz BCLK Calibration: Failed Send command for calibration to meature interval for pCode calibration \n"));
+ break;
+ }
+ MailboxS3Write(WRITE_MEASURE_INTERVAL_CMD, BiosMeasureIntervalValue);
+ break;
+
+ default:
+ DEBUG ((EFI_D_ERROR, "Unrecognized 24MHz BCLK Calibration Type \n"));
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+
+ DEBUG ((EFI_D_INFO, "24MHz BCLK calibration completed \n"));
+
+ }
+#endif // ULT_FLAG
+
+ return Status;
+}
+
+/**
+ Enable C-State support as specified by the input flags on a logical processor.
+ Configure BIOS C1 Coordination (SMI coordination)
+ Enable IO redirection coordination
+ Choose proper coordination method
+ Configure extended C-States
+
+ This function must be MP safe.
+
+ @param[in] Buffer Pointer to a ENABLE_CSTATE_PARAMS containing the necessary
+ information to enable C-States
+
+ @retval EFI_SUCCESS Processor C-State support configured successfully.
+**/
+VOID
+EFIAPI
+ApSafeEnableCStates (
+ IN OUT VOID *Buffer
+ )
+{
+ MSR_REGISTER Ia32MiscEnable;
+ MSR_REGISTER PmCfgCtrl;
+ MSR_REGISTER IoCaptAddr;
+ UINT16 C3IoAddress;
+ CPU_STEPPING mCpuSteppingId;
+ CPU_FAMILY mCpuFamilyId;
+ mCpuFamilyId = mPpmGlobalNvsAreaProtocol->Area->Cpuid & CPUID_FULL_FAMILY_MODEL;
+ mCpuSteppingId = mPpmGlobalNvsAreaProtocol->Area->Cpuid & CPUID_FULL_STEPPING;
+ ///
+ /// Extract parameters from the buffer
+ ///
+ C3IoAddress = *((UINT16 *) Buffer);
+ ///
+ /// If C-states are disabled in setup, disable C-states
+ ///
+ if (!(mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_C_STATES)) {
+ PmCfgCtrl.Qword = AsmReadMsr64 (MSR_PMG_CST_CONFIG);
+ PmCfgCtrl.Dwords.Low &= ~B_PACKAGE_C_STATE_LIMIT;
+ AsmWriteMsr64 (MSR_PMG_CST_CONFIG, PmCfgCtrl.Qword);
+ return;
+ }
+ ///
+ /// Set C-state package limit to the highest C-state enabled
+ ///
+ PmCfgCtrl.Qword = AsmReadMsr64 (MSR_PMG_CST_CONFIG);
+ if (mCpuPmConfig->PkgCStateLimit != PkgCpuDefault) {
+ PmCfgCtrl.Dwords.Low &= ~B_PACKAGE_C_STATE_LIMIT;
+
+ if ((mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_C10) && (mCpuPmConfig->PkgCStateLimit == PkgAuto)) {
+ PmCfgCtrl.Dwords.Low |= V_CSTATE_LIMIT_C10;
+ } else if ((mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_C9) && (mCpuPmConfig->PkgCStateLimit == PkgAuto)) {
+ PmCfgCtrl.Dwords.Low |= V_CSTATE_LIMIT_C9;
+ } else if ((mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_C8) && (mCpuPmConfig->PkgCStateLimit == PkgAuto)) {
+ PmCfgCtrl.Dwords.Low |= V_CSTATE_LIMIT_C8;
+ } else if ((mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_C7S) &&
+ !((mCpuFamilyId == EnumCpuHsw) && (mCpuSteppingId == EnumHswA0) && (mCpuPmConfig->PkgCStateLimit == PkgAuto))) { // When user selects Auto - Disable Package C7s state on Haswell A-step processors
+ PmCfgCtrl.Dwords.Low |= V_CSTATE_LIMIT_C7S;
+ } else if ((mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_C7)&&
+ !((mCpuFamilyId == EnumCpuHsw) && (mCpuSteppingId == EnumHswA0) && (mCpuPmConfig->PkgCStateLimit == PkgAuto))) { // When user selects Auto - Disable Package C7 state on Haswell A-step processors
+ PmCfgCtrl.Dwords.Low |= V_CSTATE_LIMIT_C7;
+ } else if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_C6) {
+ PmCfgCtrl.Dwords.Low |= V_CSTATE_LIMIT_C6;
+ } else if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_C3) {
+ PmCfgCtrl.Dwords.Low |= V_CSTATE_LIMIT_C3;
+ } else if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_C1) {
+ PmCfgCtrl.Dwords.Low |= V_CSTATE_LIMIT_C1;
+ }
+ if (mCpuPmConfig->PkgCStateLimit < PkgCMax) {
+ PmCfgCtrl.Dwords.Low &= ~B_PACKAGE_C_STATE_LIMIT;
+ PmCfgCtrl.Dwords.Low |= (mCpuPmConfig->PkgCStateLimit & B_PACKAGE_C_STATE_LIMIT);
+ }
+ }
+ ///
+ /// Enable C State IO redirection by default
+ ///
+ PmCfgCtrl.Dwords.Low |= B_IO_MWAIT_REDIRECTION_ENABLE;
+ //
+ // Enable TimedMwait
+ //
+ if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_TIMED_MWAIT) {
+ PmCfgCtrl.Dwords.Low &= (~B_TIMED_MWAIT_ENABLE);
+ PmCfgCtrl.Dwords.Low |= B_TIMED_MWAIT_ENABLE;
+ }
+ ///
+ /// Configure C-state auto-demotion
+ ///
+ PmCfgCtrl.Dwords.Low &= ~(B_C1_AUTO_DEMOTION_ENABLE | B_C3_AUTO_DEMOTION_ENABLE);
+ if (mCpuPmConfig->pFunctionEnables->C3AutoDemotion) {
+ ///
+ /// Enable C6/C7 Auto-demotion to C3
+ ///
+ PmCfgCtrl.Dwords.Low |= B_C3_AUTO_DEMOTION_ENABLE;
+ }
+ if (mCpuPmConfig->pFunctionEnables->C1AutoDemotion) {
+ ///
+ /// Enable C3/C6/C7 Auto-demotion to C1
+ ///
+ PmCfgCtrl.Dwords.Low |= B_C1_AUTO_DEMOTION_ENABLE;
+ }
+ ///
+ /// Configure C-state un-demotion
+ ///
+ PmCfgCtrl.Dwords.Low &= ~(B_C1_AUTO_UNDEMOTION_ENABLE | B_C3_AUTO_UNDEMOTION_ENABLE);
+ if (mCpuPmConfig->pFunctionEnables->C3UnDemotion) {
+ ///
+ /// Enable un-demotion from demoted C3
+ ///
+ PmCfgCtrl.Dwords.Low |= B_C3_AUTO_UNDEMOTION_ENABLE;
+ }
+ if (mCpuPmConfig->pFunctionEnables->C1UnDemotion) {
+ ///
+ /// Enable un-demotion from demoted C1
+ ///
+ PmCfgCtrl.Dwords.Low |= B_C1_AUTO_UNDEMOTION_ENABLE;
+ }
+ ///
+ /// Configure Package C-state Demotion / un-demotion - Supported only on HSW B0 and Above
+ ///
+ if (mCpuSteppingId > EnumHswA0) {
+ PmCfgCtrl.Dwords.Low &= ~(B_PKG_CSTATE_DEMOTION_ENABLE | B_PKG_CSTATE_UNDEMOTION_ENABLE);
+ if (mCpuPmConfig->pFunctionEnables->PkgCStateDemotion) {
+ ///
+ /// Enable Package C-state Demotion
+ ///
+ PmCfgCtrl.Dwords.Low |= B_PKG_CSTATE_DEMOTION_ENABLE;
+ }
+ if (mCpuPmConfig->pFunctionEnables->PkgCStateUnDemotion) {
+ ///
+ /// Enable Package C-state un-demotion
+ ///
+ PmCfgCtrl.Dwords.Low |= B_PKG_CSTATE_UNDEMOTION_ENABLE;
+ }
+ }
+ AsmWriteMsr64 (MSR_PMG_CST_CONFIG, PmCfgCtrl.Qword);
+ ///
+ /// Enable MONITOR/MWAIT support
+ /// (already done on BSP, but must be done on all components.)
+ ///
+ Ia32MiscEnable.Qword = AsmReadMsr64 (MSR_IA32_MISC_ENABLE);
+ Ia32MiscEnable.Qword |= B_MSR_IA32_MISC_ENABLE_MONITOR;
+ AsmWriteMsr64 (MSR_IA32_MISC_ENABLE, Ia32MiscEnable.Qword);
+ ///
+ /// Haswell specific configuration of I/O capture and I/O coordination SMI MSR.
+ /// Configure the base port and range in the MSR to match LVL_X settings in ACPI tables
+ /// Set I/O capture base port and range
+ ///
+ IoCaptAddr.Qword = AsmReadMsr64 (MSR_PMG_IO_CAPTURE_BASE);
+ ///
+ /// Mask off CST range and set the CST range
+ ///
+ IoCaptAddr.Dwords.Low &= ~B_MSR_PMG_CST_RANGE;
+ if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_C10) {
+ IoCaptAddr.Dwords.Low |= V_IO_CAPT_LVL7;
+ } else if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_C9) {
+ IoCaptAddr.Dwords.Low |= V_IO_CAPT_LVL6;
+ } else if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_C8) {
+ IoCaptAddr.Dwords.Low |= V_IO_CAPT_LVL5;
+ } else if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_C7) {
+ IoCaptAddr.Dwords.Low |= V_IO_CAPT_LVL4;
+ } else if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_C6) {
+ IoCaptAddr.Dwords.Low |= V_IO_CAPT_LVL3;
+ } else if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_C3) {
+ IoCaptAddr.Dwords.Low |= V_IO_CAPT_LVL2;
+ }
+ ///
+ /// Set the base CST address
+ ///
+ IoCaptAddr.Dwords.Low &= ~(V_IO_CAPT_LVL2_BASE_ADDR_MASK);
+ IoCaptAddr.Dwords.Low |= C3IoAddress;
+ AsmWriteMsr64 (MSR_PMG_IO_CAPTURE_BASE, IoCaptAddr.Qword);
+ return;
+}
+
+
+//
+// Update ACPI IdleStates tables
+//
+
+/**
+ Configure the FACP for C state support
+**/
+VOID
+ConfigureFadtCStates (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_DESCRIPTION_HEADER *Table;
+ EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *FadtPointer;
+ INTN Index;
+ UINTN Handle;
+ EFI_ACPI_TABLE_VERSION Version;
+
+ ///
+ /// Locate table with matching ID
+ ///
+ Index = 0;
+ do {
+ Status = mAcpiSupport->GetAcpiTable (mAcpiSupport, Index, (VOID **) &Table, &Version, &Handle);
+ if (Status == EFI_NOT_FOUND) {
+ break;
+ }
+ ASSERT_EFI_ERROR (Status);
+ Index++;
+ } while (Table->Signature != EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE);
+ //
+ // Can't have ACPI without FADT, so safe to assert
+ //
+ ASSERT (Table->Signature == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE);
+ FadtPointer = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *) Table;
+ //
+ // Verify expected state. Should be initialized to off during build.
+ //
+ ASSERT (FadtPointer->PLvl3Lat >= FADT_C3_LATENCY_DISABLED);
+ ///
+ /// Configure C states
+ ///
+ if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_C3) {
+ ///
+ /// Enable C3 in FADT.
+ ///
+ FadtPointer->PLvl3Lat = FADT_C3_LATENCY;
+ }
+ ///
+ /// Update the table
+ ///
+ Status = mAcpiTable->InstallAcpiTable (
+ mAcpiTable,
+ Table,
+ Table->Length,
+ &Handle
+ );
+ FreePool (Table);
+
+ return;
+} \ No newline at end of file
diff --git a/ReferenceCode/Haswell/PowerManagement/Dxe/MiscFunctions.c b/ReferenceCode/Haswell/PowerManagement/Dxe/MiscFunctions.c
new file mode 100644
index 0000000..5ad9fc8
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/Dxe/MiscFunctions.c
@@ -0,0 +1,853 @@
+/** @file
+ This file contains Processor Power Management ACPI related functions for
+ Haswell processors.
+
+ Acronyms:
+ PPM - Processor Power Management
+ TM - Thermal Monitor
+ IST - Intel(R) Speedstep technology
+ HT - Hyper-Threading Technology
+
+@copyright
+ Copyright (c) 2012-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 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
+
+**/
+#include "PowerMgmtCommon.h"
+
+///
+/// Table to convert PL1 / Pl2 Seconds into equivalent MSR values
+/// This table is used for TDP Time Window programming
+///
+UINT8 mSecondsToMsrValueMapTable[][2] = {
+ ///
+ /// Seconds, MSR Value
+ ///
+ { 1, 0x0A },
+ { 2, 0x0B },
+ { 3, 0x4B },
+ { 4, 0x0C },
+ { 5, 0x2C },
+ { 6, 0x4C },
+ { 7, 0x6C },
+ { 8, 0x0D },
+ { 10, 0x2D },
+ { 12, 0x4D },
+ { 14, 0x6D },
+ { 16, 0x0E },
+ { 20, 0x2E },
+ { 24, 0x4E },
+ { 28, 0x6E },
+ { 32, 0x0F },
+ { 40, 0x2F },
+ { 48, 0x4F },
+ { 56, 0x6F },
+ { 64, 0x10 },
+ { 80, 0x30 },
+ { 96, 0x50 },
+ { 112, 0x70 },
+ { 128, 0x11 },
+ { END_OF_TABLE, END_OF_TABLE }
+};
+
+///
+/// Table to convert PL3 Milli Seconds into equivalent MSR values
+/// This table is used for TDP Time Window programming
+///
+UINT8 mMilliSecondsToMsrValueMapTable[][2] = {
+ ///
+ /// MilliSeconds, MSR Value
+ ///
+ { 3, 0x41 },
+ { 4, 0x02 },
+ { 5, 0x22 },
+ { 6, 0x42 },
+ { 7, 0x62 },
+ { 8, 0x03 },
+ { 10, 0x23 },
+ { 12, 0x43 },
+ { 14, 0x63 },
+ { 16, 0x04 },
+ { 20, 0x24 },
+ { 24, 0x44 },
+ { 28, 0x64 },
+ { 32, 0x05 },
+ { 40, 0x25 },
+ { 48, 0x45 },
+ { 56, 0x65 },
+ { 64, 0x06 },
+ { END_OF_TABLE, END_OF_TABLE }
+};
+
+/**
+ This will perform Miscellaneous Power Management related programming.
+
+ @param[in] CtdpSupport Status of InitializeConfigurableTdp funtion
+**/
+VOID
+InitMiscFeatures (
+ EFI_STATUS CtdpSupport
+ )
+{
+ InitPchPowerSharing(mCpuPmConfig);
+ ///
+ /// Configure Package Turbo Power Limits
+ ///
+ if (CtdpSupport == EFI_SUCCESS) {
+ ConfigureCtdp (mCpuPmConfig);
+ } else {
+ ConfigurePowerLimitsNonConfigTdpSkus (mCpuPmConfig);
+ }
+
+ ///
+ /// This will perform PowerLimit 1 algorithm will be used to control Thermal Throttling features
+ ///
+ InitPl1ThermalControl (mCpuPmConfig);
+
+ ///
+ /// Configure PL3
+ ///
+ ConfigurePL3PowerLimits(mCpuPmConfig);
+
+ ///
+ /// Configure DDR RAPL PowerLimits
+ ///
+ ConfigureDdrPowerLimits(mCpuPmConfig);
+}
+
+/**
+ Private helper function to convert various Turbo Power Limit Time from Seconds to CPU units
+
+ @param[in] TimeInSeconds Time in seconds
+ @param[in] PowerLimitLevel Power Limit Level
+
+ @retval UINT8 Converted time in CPU units
+**/
+UINT8
+GetConvertedTime (
+ IN UINT32 TimeInSeconds,
+ IN UINT8 PowerLimitLevel
+ )
+{
+ UINT8 ConvertedPowerLimitTime;
+ UINT8 Index;
+
+ ///
+ /// Convert seconds to MSR value. Since not all values are programmable, we'll select
+ /// the entry from mapping table which is either equal to the user selected value. OR to a value in the mapping table
+ /// which is closest (but less than) to the user-selected value.
+ ///
+ ConvertedPowerLimitTime = 0;
+ switch(PowerLimitLevel) {
+ case PL12TimeWindowCovert:
+ ConvertedPowerLimitTime = mSecondsToMsrValueMapTable[0][1];
+ for (Index = 0; mSecondsToMsrValueMapTable[Index][0] != END_OF_TABLE; Index++) {
+ if (TimeInSeconds == mSecondsToMsrValueMapTable[Index][0]) {
+ ConvertedPowerLimitTime = mSecondsToMsrValueMapTable[Index][1];
+ break;
+ }
+ if (TimeInSeconds > mSecondsToMsrValueMapTable[Index][0]) {
+ ConvertedPowerLimitTime = mSecondsToMsrValueMapTable[Index][1];
+ } else {
+ break;
+ }
+ }
+ break;
+ case PL3TimeWindowConvert:
+ ConvertedPowerLimitTime = mMilliSecondsToMsrValueMapTable[0][1];
+ for (Index = 0; mMilliSecondsToMsrValueMapTable[Index][0] != END_OF_TABLE; Index++) {
+ if (TimeInSeconds == mMilliSecondsToMsrValueMapTable[Index][0]) {
+ ConvertedPowerLimitTime = mMilliSecondsToMsrValueMapTable[Index][1];
+ break;
+ }
+ if (TimeInSeconds > mMilliSecondsToMsrValueMapTable[Index][0]) {
+ ConvertedPowerLimitTime = mMilliSecondsToMsrValueMapTable[Index][1];
+ } else {
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ return ConvertedPowerLimitTime;
+}
+
+/**
+ Configure PMSYNC_TPR_CFG and PMSYNC_TPR_CFG2 using values returned by CPU BIOS Mail box
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+**/
+VOID
+InitPchPowerSharing (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ )
+{
+ UINT32 PcodeMailBoxPchPowerLevels;
+ UINT32 MailBoxStatus;
+ UINT32 Rcba;
+ UINT32 Index;
+ UINT8 PchPowerLevel;
+ UINT32 Data32And;
+ UINT32 Data32Or;
+ UINT16 LpcDeviceId;
+ UINT8 PchRevId;
+ UINT8 IsLptLp;
+ CPU_STEPPING CpuSteppingId;
+ CPU_FAMILY CpuFamilyId;
+
+ CpuFamilyId = mPpmGlobalNvsAreaProtocol->Area->Cpuid & CPUID_FULL_FAMILY_MODEL;
+ CpuSteppingId = mPpmGlobalNvsAreaProtocol->Area->Cpuid & CPUID_FULL_STEPPING;
+
+ ///
+ /// PCH Power sharing supported only on HSW ULT.
+ ///
+ if (CpuFamilyId != EnumCpuHswUlt) {
+ return;
+ }
+
+ ///
+ /// Read PCH Power Limit from PCODE Mail Box.
+ ///
+ MailboxRead (MAILBOX_TYPE_PCODE,READ_PCH_POWER_LEVELS_CMD,&PcodeMailBoxPchPowerLevels,&MailBoxStatus);
+
+ DEBUG ((EFI_D_ERROR, "Read PCH Power Limit from PCODE Mail Box : %x \n",PcodeMailBoxPchPowerLevels));
+ Rcba = MmioRead32 (
+ MmPciAddress (
+ 0,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ R_PCH_LPC_RCBA
+ )
+ );
+ Rcba &= (UINT32) (~BIT0);
+ if (MailBoxStatus == PCODE_MAILBOX_CC_SUCCESS) {
+ ///
+ /// Program RCBA+PMSYNC_TPR_CONFIG PCH power limit values.
+ /// READ_PCH_POWER_LEVELS_CMD MailBox[0:5],MailBox[6:11],MailBox[12:17] to PCHReg [0:4],[8:12],[16:20]
+ ///
+ Data32And =0x0;
+ Data32Or =0x0;
+
+ for (Index = 0; Index < HSW_ULT_PCH_POWER_LEVELS; Index++) {
+ PchPowerLevel = PcodeMailBoxPchPowerLevels & 0x3F;
+ PcodeMailBoxPchPowerLevels = PcodeMailBoxPchPowerLevels >> 6;
+ Data32And |= 0x1F << (Index * 8);
+ Data32Or |= (PchPowerLevel & 0x1F) << (Index * 8);
+ }
+ Data32And = ~Data32And;
+ MmioAndThenOr32(Rcba+PMSYNC_TPR_CONFIG,Data32And,Data32Or);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (Rcba + PMSYNC_TPR_CONFIG),
+ 1,
+ (VOID *) (UINTN) (Rcba + PMSYNC_TPR_CONFIG)
+ );
+ } else {
+ DEBUG ((EFI_D_ERROR, "Failure - Read PCH Power Limit from PCODE Mail Box\n"));
+ }
+ ///
+ /// Extended PCH power sharing supported on HSW ULT C0 & LPT-LP B0 and later
+ ///
+ ///
+ PchRevId = MmioRead8 (
+ MmPciAddress (0,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ R_PCH_LPC_RID)
+ );
+
+ LpcDeviceId = MmioRead16 (
+ MmPciAddress (0,
+ DEFAULT_PCI_BUS_NUMBER_PCH,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ R_PCH_LPC_DEVICE_ID)
+ );
+ IsLptLp = IS_PCH_LPTLP_LPC_DEVICE_ID(LpcDeviceId);
+
+ if(IsLptLp && (PchRevId < V_PCH_LPT_LPC_RID_2) && (CpuSteppingId < EnumHswUltC0)) {
+ return;
+ }
+ ///
+ /// Program RCBA+PMSYNC_TPR_CONFIG Extnded PCH power limit values.
+ /// READ_PCH_POWER_LEVELS_CMD-MailBox[23:18],READ_EXT_PCH_POWER_LEVELS_CMD- MailBox[6:11],MailBox[12:17],MailBox[18:22] to PCHReg [0:4],[8:12],[16:20],[24:28]
+ ///
+ Data32And = 0x1F;
+ Data32Or = (PcodeMailBoxPchPowerLevels & 0x1F);
+ ///
+ /// Read Extended PCH Power Limit from PCODE Mail Box.
+ ///
+ MailboxRead (MAILBOX_TYPE_PCODE,READ_EXT_PCH_POWER_LEVELS_CMD,&PcodeMailBoxPchPowerLevels,&MailBoxStatus);
+ DEBUG ((EFI_D_ERROR, "Read Extended PCH Power Limit from PCODE Mail Box : %x \n",PcodeMailBoxPchPowerLevels));
+ if (MailBoxStatus == PCODE_MAILBOX_CC_SUCCESS) {
+ for (Index = 1; Index < EXTENDED_PCH_POWER_LEVELS; Index++) {
+ PchPowerLevel = PcodeMailBoxPchPowerLevels & 0x3F;
+ PcodeMailBoxPchPowerLevels = PcodeMailBoxPchPowerLevels >> 6;
+ Data32And |= 0x1F << (Index * 8);
+ Data32Or |= (PchPowerLevel & 0x1F) << (Index * 8);
+ }
+ Data32And = ~Data32And;
+ MmioAndThenOr32(Rcba+PMSYNC_TPR_CONFIG2,Data32And,Data32Or);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (Rcba + PMSYNC_TPR_CONFIG2),
+ 1,
+ (VOID *) (UINTN) (Rcba + PMSYNC_TPR_CONFIG2)
+ );
+ } else {
+ DEBUG ((EFI_D_ERROR, "Failure -Extended Read PCH Power Limit from PCODE Mail Box\n"));
+ }
+}
+
+/**
+ Locks down all settings.
+
+ @param[in] CpuPmConfig Pointer to PPM Policy structure.
+**/
+VOID
+PpmLockDown (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ )
+{
+ MSR_REGISTER TempMsr;
+ ///
+ /// Program PMG_CST_CONFIG MSR [15] (CFG lock bit)
+ ///
+ RunOnAllLogicalProcessors (ApSafeLockDown, CpuPmConfig);
+ ///
+ /// Lock Package power limit MSR
+ ///
+ TempMsr.Qword = AsmReadMsr64 (MSR_PACKAGE_POWER_LIMIT);
+ TempMsr.Dwords.High &= ~(B_POWER_LIMIT_LOCK);
+ if (CpuPmConfig->pTurboSettings->TurboPowerLimitLock) {
+ TempMsr.Dwords.High |= B_POWER_LIMIT_LOCK;
+ }
+ AsmWriteMsr64 (MSR_PACKAGE_POWER_LIMIT, TempMsr.Qword);
+ ///
+ /// Program the OverClocking Lock Bit.
+ ///
+ TempMsr.Qword = AsmReadMsr64 (MSR_FLEX_RATIO);
+ TempMsr.Dwords.Low &= ~(B_OVERCLOCKING_LOCK);
+ if (CpuPmConfig->pPpmLockEnables->OverclockingLock) {
+ TempMsr.Dwords.Low |= B_OVERCLOCKING_LOCK;
+ }
+ AsmWriteMsr64 (MSR_FLEX_RATIO, TempMsr.Qword);
+ ///
+ /// Program the PROCHOT_Lock
+ ///
+ TempMsr.Qword = AsmReadMsr64 (MSR_POWER_CTL);
+ TempMsr.Dwords.Low &= ~(B_MSR_POWER_CTL_PROC_HOT_LOCK);
+ if (CpuPmConfig->pPpmLockEnables->ProcHotLock) {
+ TempMsr.Dwords.Low |= B_MSR_POWER_CTL_PROC_HOT_LOCK;
+ }
+ AsmWriteMsr64 (MSR_POWER_CTL, TempMsr.Qword);
+ ///
+ /// Program Ddr RAPL LIMIT Lock
+ ///
+ TempMsr.Qword = AsmReadMsr64 (MSR_DDR_RAPL_LIMIT);
+ TempMsr.Dwords.High &= ~(B_POWER_LIMIT_LOCK);
+ if (CpuPmConfig->pTurboSettings->TurboPowerLimitLock) {
+ TempMsr.Dwords.High |= B_POWER_LIMIT_LOCK;
+ }
+ AsmWriteMsr64 (MSR_DDR_RAPL_LIMIT, TempMsr.Qword);
+
+ return;
+}
+
+/**
+ Lock MSR_PMG_CST_CONFIG.
+ This function must be MP safe.
+
+ @param[in] Buffer Not used (needed for API compatibility)
+
+ @retval EFI_SUCCESS Processor C-State locked successfully.
+**/
+VOID
+EFIAPI
+ApSafeLockDown (
+ IN OUT VOID *Buffer
+ )
+{
+ MSR_REGISTER PmCfgCtrl;
+ POWER_MGMT_CONFIG *CpuPmConfig;
+ UINT8 CfgLock;
+
+ CpuPmConfig = (POWER_MGMT_CONFIG *) Buffer;
+ if (CpuPmConfig == NULL) {
+ CfgLock = PPM_ENABLE;
+ } else {
+ CfgLock = (UINT8) CpuPmConfig->pPpmLockEnables->PmgCstCfgCtrlLock;
+ }
+ PmCfgCtrl.Qword = AsmReadMsr64 (MSR_PMG_CST_CONFIG);
+ PmCfgCtrl.Dwords.Low &= ~B_CST_CONTROL_LOCK;
+ if (CfgLock == PPM_ENABLE) {
+ PmCfgCtrl.Dwords.Low |= B_CST_CONTROL_LOCK;
+ }
+ AsmWriteMsr64 (MSR_PMG_CST_CONFIG, PmCfgCtrl.Qword);
+
+ return;
+}
+
+/**
+ Runs the specified procedure on all logical processors, passing in the
+ parameter buffer to the procedure.
+
+ @param[in] Procedure The function to be run.
+ @param[in] Buffer Pointer to a parameter buffer.
+
+ @retval EFI_SUCCESS
+**/
+EFI_STATUS
+RunOnAllLogicalProcessors (
+ IN OUT EFI_AP_PROCEDURE Procedure,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+
+ ///
+ /// Run the procedure on all logical processors.
+ ///
+ (*Procedure)(Buffer);
+ Status = mMpService->StartupAllAPs (
+ mMpService,
+ (EFI_AP_PROCEDURE) Procedure,
+ TRUE,
+ NULL,
+ MP_TIMEOUT_FOR_STARTUP_ALL_APS,
+ Buffer,
+ NULL
+ );
+
+ return Status;
+}
+
+/**
+ Configures the RFI Tunning MSR (0xE3) for FIVR switching freq.
+
+ @param[in] CpuPmConfig Pointer to PPM Policy structure.
+**/
+VOID
+InitFivrSwitchingFreq (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ )
+{
+ MSR_REGISTER RfiTuningValue;
+ UINT16 FreqTuningOffsetValue;
+ UINT32 Remainder;
+
+ ///
+ /// Check if we have to change the RFI Freq Tunning offset.
+ /// Check PLATFORM_INFO MSR[25] == 1 before accessing the MSR_RFI_TUNNING
+ ///
+ if ((CpuPmConfig->RfiFreqTunningOffset != AUTO) &&
+ ((AsmReadMsr64 (MSR_PLATFORM_INFO)) & B_FIVR_RFI_TUNING_AVAIL)
+ ) {
+ ///
+ /// Convert the Policy Freq Tunning offset.
+ /// Target frequency encoding = int(value*2^16+0.5) for positive offsets and inv(int(value*2^16+0.5))+1 for negative offsets
+ ///
+ FreqTuningOffsetValue = (UINT16) DivU64x32Remainder (
+ (UINT64) (CpuPmConfig->RfiFreqTunningOffset * (1 << 16)),
+ 1000,
+ &Remainder
+ );
+ if (Remainder >= 500) {
+ FreqTuningOffsetValue += 1;
+ }
+ ///
+ /// Check if Freq Tunning offset value is -ve
+ ///
+ if (CpuPmConfig->RfiFreqTunningOffsetIsNegative == 1) {
+ FreqTuningOffsetValue = (UINT16) (~FreqTuningOffsetValue + 1);
+ }
+ ///
+ /// Write to the RFI_TUNING_MSR. System BIOS must set the desired frequency offset in bits 15:0 of this MSR.
+ ///
+ RfiTuningValue.Qword = AsmReadMsr64 (MSR_RFI_TUNNING);
+
+ ///
+ /// Set the Tuning Frequency
+ ///
+ RfiTuningValue.Qword = ((RfiTuningValue.Qword & V_FREQ_TUNNING_MASK) | FreqTuningOffsetValue);
+ AsmWriteMsr64 (MSR_RFI_TUNNING, RfiTuningValue.Qword);
+ }
+}
+
+/**
+ Update the SSDT table pointers and config DWORD CFGD with the PpmFlags current configuration value
+**/
+VOID
+PatchCpuPmTable (
+ VOID
+ )
+{
+ UINT8 *CurrPtr;
+ UINT32 *Signature;
+ SSDT_LAYOUT *SsdtPackage;
+
+ ///
+ /// Locate the SSDT package
+ ///
+ SsdtPackage = NULL;
+ CurrPtr = (UINT8 *) mCpuPmTable;
+ for (CurrPtr; CurrPtr <= ((UINT8 *) mCpuPmTable + mCpuPmTable->Length); CurrPtr++) {
+ Signature = (UINT32 *) (CurrPtr + 1);
+ if ((*CurrPtr == AML_NAME_OP) && *Signature == EFI_SIGNATURE_32 ('S', 'S', 'D', 'T')) {
+ ///
+ /// Update the SSDT table pointers for dynamically loaded tables
+ ///
+ SsdtPackage = (SSDT_LAYOUT *) CurrPtr;
+ ///
+ /// Set the P-State SSDT table information
+ ///
+ SsdtPackage->Cpu0IstAddr = (UINT32) (UINTN) mCpu0IstTable;
+ SsdtPackage->Cpu0IstLen = mCpu0IstTable->Length;
+ SsdtPackage->ApIstAddr = (UINT32) (UINTN) mApIstTable;
+ SsdtPackage->ApIstLen = mApIstTable->Length;
+ ///
+ /// Set the C-State SSDT table information
+ ///
+ SsdtPackage->Cpu0CstAddr = (UINT32) (UINTN) mCpu0CstTable;
+ SsdtPackage->Cpu0CstLen = mCpu0CstTable->Length;
+ SsdtPackage->ApCstAddr = (UINT32) (UINTN) mApCstTable;
+ SsdtPackage->ApCstLen = mApCstTable->Length;
+ }
+ ///
+ /// Update the PPM GlobalNvs area
+ ///
+ if ((*CurrPtr == AML_OPREGION_OP) && *Signature == EFI_SIGNATURE_32 ('P', 'P', 'M', 'T')) {
+ ASSERT_EFI_ERROR (*(UINT32 *) (CurrPtr + 1 + sizeof (*Signature) + 2) == 0xFFFF0000);
+ ASSERT_EFI_ERROR (*(UINT16 *) (CurrPtr + 1 + sizeof (*Signature) + 2 + sizeof (UINT32) + 1) == 0xAA55);
+ ///
+ /// PPM Global NVS Area address
+ ///
+ *(UINT32 *) (CurrPtr + 1 + sizeof (*Signature) + 2) = (UINT32) (UINTN) mPpmGlobalNvsAreaProtocol->Area;
+ ///
+ /// PPM Global NVS Area size
+ ///
+ *(UINT16 *) (CurrPtr + 1 + sizeof (*Signature) + 2 + sizeof (UINT32) + 1) = sizeof (PPM_GLOBAL_NVS_AREA);
+ break;
+ }
+ }
+ //
+ // Assert if we didn't update the PM table
+ //
+ ASSERT (SsdtPackage != NULL);
+
+ return;
+}
+
+/**
+ Locate the PPM ACPI tables data file and read ACPI SSDT tables.
+ Publish the appropriate SSDT based on current configuration and capabilities.
+
+ @retval EFI_SUCCESS - On success
+ @retval EFI_NOT_FOUND - Required firmware volume not found
+ @retval - Appropiate failure code on error
+**/
+EFI_STATUS
+InitializePpmAcpiTable (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN NumberOfHandles;
+ EFI_FV_FILETYPE FileType;
+ UINT32 FvStatus;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ UINTN Size;
+ UINTN i;
+ EFI_FIRMWARE_VOLUME_PROTOCOL *FwVol;
+ INTN Instance;
+ EFI_ACPI_TABLE_VERSION Version;
+ EFI_ACPI_COMMON_HEADER *CurrentTable;
+ EFI_ACPI_DESCRIPTION_HEADER *TempTable;
+ UINTN AcpiTableHandle;
+
+ ///
+ /// Locate Firmware volume protocol.
+ /// There is little chance we can't find an FV protocol
+ ///
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiFirmwareVolumeProtocolGuid,
+ NULL,
+ &NumberOfHandles,
+ &HandleBuffer
+ );
+ ASSERT_EFI_ERROR (Status);
+ ///
+ /// Look for FV with ACPI storage file
+ ///
+ FwVol = NULL;
+ for (i = 0; i < NumberOfHandles; i++) {
+ ///
+ /// Get the protocol on this handle
+ /// This should not fail because of LocateHandleBuffer
+ ///
+ Status = gBS->HandleProtocol (
+ HandleBuffer[i],
+ &gEfiFirmwareVolumeProtocolGuid,
+ (VOID **) &FwVol
+ );
+ ASSERT_EFI_ERROR (Status);
+ ///
+ /// See if it has the ACPI storage file
+ ///
+ Size = 0;
+ FvStatus = 0;
+ Status = FwVol->ReadFile (
+ FwVol,
+ &gPowerMgmtAcpiTableStorageGuid,
+ NULL,
+ &Size,
+ &FileType,
+ &Attributes,
+ &FvStatus
+ );
+ ///
+ /// If we found it, then we are done
+ ///
+ if (Status == EFI_SUCCESS) {
+ break;
+ }
+ }
+ ///
+ /// Our exit status is determined by the success of the previous operations
+ /// If the protocol was found, Instance already points to it.
+ /// Free any allocated buffers
+ ///
+ FreePool (HandleBuffer);
+ ///
+ /// Sanity check that we found our data file
+ ///
+ ASSERT (FwVol != NULL);
+ if (FwVol == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ ///
+ /// By default, a table belongs in all ACPI table versions published.
+ ///
+ Version = EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0;
+ ///
+ /// Read tables from the storage file.
+ ///
+ Instance = 0;
+ CurrentTable = NULL;
+ while (Status == EFI_SUCCESS) {
+ Status = FwVol->ReadSection (
+ FwVol,
+ &gPowerMgmtAcpiTableStorageGuid,
+ EFI_SECTION_RAW,
+ Instance,
+ (VOID **) &CurrentTable,
+ &Size,
+ &FvStatus
+ );
+ if (!EFI_ERROR (Status)) {
+ ///
+ /// Check the table ID to modify the table
+ ///
+ switch (((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable)->OemTableId) {
+ case (EFI_SIGNATURE_64 ('C', 'p', 'u', '0', 'I', 's', 't', 0)):
+ mCpu0IstTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable;
+ if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_EIST) {
+ ///
+ /// Patch the native _PSS package with the GV3 values
+ ///
+ Status = AcpiPatchPss ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ break;
+ case (EFI_SIGNATURE_64 ('C', 'p', 'u', '0', 'C', 's', 't', 0)):
+ mCpu0CstTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable;
+ break;
+ case (EFI_SIGNATURE_64 ('C', 'p', 'u', '0', 'T', 's', 't', 0)):
+ mCpu0TstTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable;
+ break;
+ case (EFI_SIGNATURE_64 ('A', 'p', 'I', 's', 't', 0, 0, 0)):
+ mApIstTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable;
+ break;
+ case (EFI_SIGNATURE_64 ('A', 'p', 'C', 's', 't', 0, 0, 0)):
+ mApCstTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable;
+ break;
+ case (EFI_SIGNATURE_64 ('A', 'p', 'T', 's', 't', 0, 0, 0)):
+ mApTstTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable;
+ break;
+ case (EFI_SIGNATURE_64 ('C', 'p', 'u', 'P', 'm', 0, 0, 0)):
+ mCpuPmTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable;
+ break;
+ case (EFI_SIGNATURE_64 ('L', 'a', 'k', 'e', 'T','i', 'n', 'y')):
+ mLakeTinyTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable;
+ break;
+ case (EFI_SIGNATURE_64 ('C', 't', 'd', 'p', 'B', 0, 0, 0)):
+ mCtdpTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable;
+ break;
+ default:
+ break;
+ }
+ Instance++; // Increment the instance
+ CurrentTable = NULL;
+ }
+ }
+ ///
+ /// Statically load IST SSDT if EIST is enabled
+ ///
+ if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_EIST) {
+ AcpiTableHandle = 0;
+ Status = mAcpiTable->InstallAcpiTable (
+ mAcpiTable,
+ mCpu0IstTable,
+ mCpu0IstTable->Length,
+ &AcpiTableHandle
+ );
+ //
+ // Free this table as it has been copied into ACPI tables
+ //
+ FreePool (mCpu0IstTable);
+ }
+ ///
+ /// If we are CMP, then the PPM tables are dynamically loaded:
+ /// We need to publish the CpuPm table to the ACPI tables, and move the CST
+ /// tables that are dynamically loaded to a separate location so that we can fix the
+ /// addresses in the CpuPm table.
+ /// Otherwise (non-CMP):
+ /// We need to publish CPU 0 tables only, and CST tables only if CST is enabled
+ ///
+ if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_CMP) {
+ //
+ // Copy tables to our own location and checksum them
+ //
+ Status = (gBS->AllocatePool) (EfiReservedMemoryType, mApIstTable->Length, (VOID **) &TempTable);
+ ASSERT_EFI_ERROR (Status);
+ CopyMem (TempTable, mApIstTable, mApIstTable->Length);
+ FreePool (mApIstTable);
+ mApIstTable = TempTable;
+ AcpiChecksum (mApIstTable, mApIstTable->Length, EFI_FIELD_OFFSET (EFI_ACPI_DESCRIPTION_HEADER, Checksum));
+ Status = (gBS->AllocatePool) (EfiReservedMemoryType, mCpu0CstTable->Length, (VOID **) &TempTable);
+ ASSERT_EFI_ERROR (Status);
+ CopyMem (TempTable, mCpu0CstTable, mCpu0CstTable->Length);
+ FreePool (mCpu0CstTable);
+ mCpu0CstTable = TempTable;
+ AcpiChecksum (mCpu0CstTable, mCpu0CstTable->Length, EFI_FIELD_OFFSET (EFI_ACPI_DESCRIPTION_HEADER, Checksum));
+ Status = (gBS->AllocatePool) (EfiReservedMemoryType, mApCstTable->Length, (VOID **) &TempTable);
+ ASSERT_EFI_ERROR (Status);
+ CopyMem (TempTable, mApCstTable, mApCstTable->Length);
+ FreePool (mApCstTable);
+ mApCstTable = TempTable;
+ AcpiChecksum (mApCstTable, mApCstTable->Length, EFI_FIELD_OFFSET (EFI_ACPI_DESCRIPTION_HEADER, Checksum));
+ } else {
+ //
+ // CMP disabled, so statically load the tables
+ //
+ // Add CST SSDT if C states are enabled
+ //
+ if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_C_STATES) {
+ AcpiTableHandle = 0;
+ Status = mAcpiTable->InstallAcpiTable (
+ mAcpiTable,
+ mCpu0CstTable,
+ mCpu0CstTable->Length,
+ &AcpiTableHandle
+ );
+ }
+ ///
+ /// Since we are UP, there is no need for the CPU 1 tables
+ ///
+ ///
+ /// Free all tables, since they have been copied into ACPI tables by ACPI support protocol
+ ///
+ FreePool (mCpu0CstTable);
+ FreePool (mApIstTable);
+ FreePool (mApCstTable);
+ }
+ ///
+ /// Update the CpuPm SSDT table in the ACPI tables.
+ ///
+ PatchCpuPmTable ();
+ AcpiTableHandle = 0;
+ Status = mAcpiTable->InstallAcpiTable (
+ mAcpiTable,
+ mCpuPmTable,
+ mCpuPmTable->Length,
+ &AcpiTableHandle
+ );
+ FreePool (mCpuPmTable);
+ if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_TSTATES) {
+ ///
+ /// Load the Cpu0Tst SSDT table in the ACPI tables
+ ///
+ AcpiTableHandle = 0;
+ Status = mAcpiTable->InstallAcpiTable (
+ mAcpiTable,
+ mCpu0TstTable,
+ mCpu0TstTable->Length,
+ &AcpiTableHandle
+ );
+ FreePool (mCpu0TstTable);
+ ///
+ /// If the CMP is enabled then load the ApTst SSDT table in the ACPI tables
+ ///
+ if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_CMP) {
+ AcpiTableHandle = 0;
+ Status = mAcpiTable->InstallAcpiTable (
+ mAcpiTable,
+ mApTstTable,
+ mApTstTable->Length,
+ &AcpiTableHandle
+ );
+ }
+ }
+ FreePool (mApTstTable);
+ ///
+ /// Load LakeTiny SSDT only when it is enabled in policy and laketiny SSDT is included.
+ ///
+ if ((mCpuPmConfig->pFunctionEnables->LakeTiny) && (mLakeTinyTable != NULL)) {
+ AcpiTableHandle = 0;
+ Status = mAcpiTable->InstallAcpiTable (
+ mAcpiTable,
+ mLakeTinyTable,
+ mLakeTinyTable->Length,
+ &AcpiTableHandle
+ );
+ FreePool (mLakeTinyTable);
+ }
+ ///
+ /// Load Ctdp SSDT
+ ///
+ if (mCpuPmConfig->pTurboSettings->ConfigTdpBios == 1) {
+ AcpiTableHandle = 0;
+ Status = mAcpiTable->InstallAcpiTable (
+ mAcpiTable,
+ mCtdpTable,
+ mCtdpTable->Length,
+ &AcpiTableHandle
+ );
+ FreePool (mCtdpTable);
+ }
+
+ return Status;
+} \ No newline at end of file
diff --git a/ReferenceCode/Haswell/PowerManagement/Dxe/PerformanceStates.c b/ReferenceCode/Haswell/PowerManagement/Dxe/PerformanceStates.c
new file mode 100644
index 0000000..bcb03b2
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/Dxe/PerformanceStates.c
@@ -0,0 +1,930 @@
+/** @file
+ This file contains P States and Turbo Power Management configuration functions for
+ Haswell processors.
+
+ Acronyms:
+ PPM - Processor Power Management
+ TM - Thermal Monitor
+ IST - Intel(R) Speedstep technology
+ HT - Hyper-Threading Technology
+
+@copyright
+ Copyright (c) 2012 - 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 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
+
+**/
+#include "PowerMgmtCommon.h"
+
+//(AMI_CHG)>
+VOID
+EFIAPI
+ApSafeSetEnergyPolicy (
+ IN OUT VOID *Buffer
+ );
+//<(AMI_CHG)
+
+extern UINT16 mCpuConfigTdpBootRatio;
+
+/**
+ Initializes P States and Turbo Power management features
+**/
+VOID
+InitializePStates (
+ VOID
+ )
+{
+ MSR_REGISTER Ia32MiscEnableMsr;
+
+ //
+ // InitTurboRatioLimits has to be called before InitGV3 as InitGV3 uses the Turbo Ratio Limit programmed.
+ //
+ InitTurboRatioLimits (mCpuPmConfig); ///< Initialize InitTurboRatioLimits
+
+ InitEnergyEfficientPState (mCpuPmConfig); ///< Initialize Energy Efficient P-state
+
+ //
+ // Initialize P states
+ //
+ if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_EIST) {
+ InitGv3 (mFvidPointer, mCpuPmConfig);
+ mNumberOfStates = mFvidPointer[0].FvidHeader.Gv3States;
+ } else {
+ //
+ // Clear EIST bit in IA32 Misc Enable MSR that was intially set in PEI
+ //
+ Ia32MiscEnableMsr.Qword = AsmReadMsr64 (MSR_IA32_MISC_ENABLE);
+ Ia32MiscEnableMsr.Qword &= ~B_MSR_IA32_MISC_ENABLE_EIST;
+ ///
+ /// Disable Turbo if EIST is disabled
+ ///
+ if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_TURBO) {
+ Ia32MiscEnableMsr.Qword |= (UINT64)B_MSR_IA32_MISC_DISABLE_TURBO;
+ }
+ AsmWriteMsr64 (MSR_IA32_MISC_ENABLE, Ia32MiscEnableMsr.Qword);
+ }
+
+ ///
+ /// Initialize PAIR Configuration
+ /// HSW BWG Rev 0.6.0, Section 16.4.1 Power Aware Interrupt Routing
+ ///
+ InitPpmIrmConfiguration (mCpuPmConfig);
+
+}
+
+/**
+ Initializes Turbo Ratio limits in the processor.
+
+ @param[in] CpuPmConfig Pointer to PPM Policy protocol instance
+**/
+VOID
+InitTurboRatioLimits (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ )
+{
+ MSR_REGISTER TurboRatioLimit;
+ MSR_REGISTER CoreThreadCount;
+ MSR_REGISTER FlexRatioMsr;
+ UINT8 CoreCount;
+ UINT8 OverclockingBins;
+ UINT8 OneCoreRatioLimit;
+ UINT8 TwoCoreRatioLimit;
+ UINT8 ThreeCoreRatioLimit;
+ UINT8 FourCoreRatioLimit;
+
+ ///
+ /// Check if processor turbo-ratio can be overriden
+ ///
+ // Haswell BWG Section 15.13.7
+ // If PLATFORM INFO MSR [28] == 1
+ //
+ if (!mRatioLimitProgrammble) {
+ DEBUG ((EFI_D_WARN, "Turbo Ratio Limit is NOT programmable. Platform Info MSR (0xCE) [28] is not set \n"));
+ return;
+ }
+ ///
+ /// Read the overclocking bins
+ ///
+ FlexRatioMsr.Qword = AsmReadMsr64 (MSR_FLEX_RATIO);
+ OverclockingBins = (UINT8) RShiftU64 ((FlexRatioMsr.Dwords.Low & B_OVERCLOCKING_BINS), 17);
+ if (FlexRatioMsr.Dwords.Low & B_OVERCLOCKING_LOCK) { ///< Check for Overclocking Lock bit
+ DEBUG ((EFI_D_ERROR, "ERROR: OverClocking Lock Bit is set. Disable the Lock and reset the system\n"));
+ return;
+ }
+ TurboRatioLimit.Qword = AsmReadMsr64 (MSR_TURBO_RATIO_LIMIT);
+ OneCoreRatioLimit = (UINT8) (TurboRatioLimit.Dwords.Low & B_MSR_TURBO_RATIO_LIMIT_1C);
+ TwoCoreRatioLimit = (UINT8) RShiftU64 (
+ (TurboRatioLimit.Dwords.Low & B_MSR_TURBO_RATIO_LIMIT_2C),
+ N_MSR_TURBO_RATIO_LIMIT_2C
+ );
+ ThreeCoreRatioLimit = (UINT8) RShiftU64 (
+ (TurboRatioLimit.Dwords.Low & B_MSR_TURBO_RATIO_LIMIT_3C),
+ N_MSR_TURBO_RATIO_LIMIT_3C
+ );
+ FourCoreRatioLimit = (UINT8) RShiftU64 (
+ (TurboRatioLimit.Dwords.Low & B_MSR_TURBO_RATIO_LIMIT_4C),
+ N_MSR_TURBO_RATIO_LIMIT_4C
+ );
+ ///
+ /// For Overclocking and locked parts, verify ratio overide is within the allowable limits
+ /// Locked parts will have OverclockingBins value as 0 so the below condition will take care of locked parts also
+ ///
+ if (OverclockingBins < MAX_OVERCLOCKING_BINS) {
+ if (CpuPmConfig->pRatioLimit[0] > (OneCoreRatioLimit + OverclockingBins)) {
+ CpuPmConfig->pRatioLimit[0] = OneCoreRatioLimit + OverclockingBins;
+ }
+ if (CpuPmConfig->pRatioLimit[1] > (TwoCoreRatioLimit + OverclockingBins)) {
+ CpuPmConfig->pRatioLimit[1] = TwoCoreRatioLimit + OverclockingBins;
+ }
+ if (CpuPmConfig->pRatioLimit[2] > (ThreeCoreRatioLimit + OverclockingBins)) {
+ CpuPmConfig->pRatioLimit[2] = ThreeCoreRatioLimit + OverclockingBins;
+ }
+ if (CpuPmConfig->pRatioLimit[3] > (FourCoreRatioLimit + OverclockingBins)) {
+ CpuPmConfig->pRatioLimit[3] = FourCoreRatioLimit + OverclockingBins;
+ }
+ }
+
+ ///
+ /// Max Turbo ratio or P0 = Fused 1C Turbo Ratio Limit + No of over clocking Bins.
+ ///
+ mTurboBusRatio = OneCoreRatioLimit + OverclockingBins;
+ ///
+ /// Initialize turbo ratio limit MSR.
+ /// Find the number of active cores and initialize the ratio limits only if they are available.
+ ///
+ CoreThreadCount.Qword = AsmReadMsr64 (MSR_CORE_THREAD_COUNT);
+ CoreCount = (UINT8) RShiftU64 (CoreThreadCount.Dwords.Low, N_CORE_COUNT_OFFSET);
+ if (CpuPmConfig->pRatioLimit[0] >= CpuPmConfig->pRatioLimit[1] &&
+ CpuPmConfig->pRatioLimit[0] >= CpuPmConfig->pRatioLimit[2] &&
+ CpuPmConfig->pRatioLimit[0] >= CpuPmConfig->pRatioLimit[3] &&
+ CpuPmConfig->pRatioLimit[1] >= mMaxBusRatio &&
+ CpuPmConfig->pRatioLimit[2] >= mMaxBusRatio &&
+ CpuPmConfig->pRatioLimit[3] >= mMaxBusRatio
+ ) {
+ if (CoreCount >= 1) {
+ TurboRatioLimit.Dwords.Low &= ~B_MSR_TURBO_RATIO_LIMIT_1C;
+ TurboRatioLimit.Dwords.Low |= CpuPmConfig->pRatioLimit[0];
+ }
+ if (CoreCount >= 2) {
+ TurboRatioLimit.Dwords.Low &= ~B_MSR_TURBO_RATIO_LIMIT_2C;
+ TurboRatioLimit.Dwords.Low |= LShiftU64 (CpuPmConfig->pRatioLimit[1], 8);
+ }
+ if (CoreCount >= 3) {
+ TurboRatioLimit.Dwords.Low &= ~B_MSR_TURBO_RATIO_LIMIT_3C;
+ TurboRatioLimit.Dwords.Low |= LShiftU64 (CpuPmConfig->pRatioLimit[2], 16);
+ }
+ if (CoreCount >= 4) {
+ TurboRatioLimit.Dwords.Low &= ~B_MSR_TURBO_RATIO_LIMIT_4C;
+ TurboRatioLimit.Dwords.Low |= LShiftU64 (CpuPmConfig->pRatioLimit[3], 24);
+ }
+ AsmWriteMsr64 (MSR_TURBO_RATIO_LIMIT, TurboRatioLimit.Qword);
+ }
+ //
+ // For fully unlocked CPU's, configure Turbo Ratio as 0xFF (max possible P-State)
+ //
+ if (OverclockingBins == MAX_OVERCLOCKING_BINS) {
+ mTurboBusRatio = 0xFF;
+ }
+
+ return;
+}
+
+/**
+ Initializes Energy efficient P-state feature.
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+**/
+VOID
+InitEnergyEfficientPState (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ )
+{
+ MSR_REGISTER PowerCtlMsr;
+
+ ///
+ /// Configure Energy Efficient P-state : POWER_CTL[18]
+ ///
+ PowerCtlMsr.Qword = AsmReadMsr64 (MSR_POWER_CTL);
+ PowerCtlMsr.Dwords.Low &= ~B_ENERGY_EFFICIENT_P_STATE_FEATURE_ENABLE;
+ if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_EEPST) {
+ PowerCtlMsr.Dwords.Low |= B_ENERGY_EFFICIENT_P_STATE_FEATURE_ENABLE;
+ }
+ AsmWriteMsr64 (MSR_POWER_CTL, PowerCtlMsr.Qword);
+
+//(AMI_CHG)>
+ if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_EEPST) {
+ RunOnAllLogicalProcessors (ApSafeSetEnergyPolicy, CpuPmConfig);
+ }
+//<(AMI_CHG)
+ return;
+}
+
+/**
+ Sets the MSR_IA32_ENERGY_PERFROMANCE_BIAS.Energy Efficiency Policy.
+ This function must be MP safe.
+
+ @param[in] Buffer Pointer to PPM Policy
+
+ @retval EFI_SUCCESS Energy policy is set successfully.
+**/
+//(AMI_CHG)>
+VOID
+EFIAPI
+ApSafeSetEnergyPolicy (
+ IN OUT VOID *Buffer
+ )
+{
+ POWER_MGMT_CONFIG *CpuPmConfig;
+ MSR_REGISTER Ia32EnergyPerfBiasMsr;
+
+ CpuPmConfig = (POWER_MGMT_CONFIG *) Buffer;
+ Ia32EnergyPerfBiasMsr.Qword = AsmReadMsr64 (MSR_IA32_ENERGY_PERFORMANCE_BIAS);
+ Ia32EnergyPerfBiasMsr.Dwords.Low &= ~B_ENERGY_POLICY_MASK;
+ Ia32EnergyPerfBiasMsr.Dwords.Low |= CpuPmConfig->pTurboSettings->EnergyPolicy;
+ AsmWriteMsr64 (MSR_IA32_ENERGY_PERFORMANCE_BIAS, Ia32EnergyPerfBiasMsr.Qword);
+
+ return;
+}
+/*EFI_STATUS
+ApSafeSetEnergyPolicy (
+ IN OUT VOID *Buffer
+ )
+{
+ POWER_MGMT_CONFIG *CpuPmConfig;
+ MSR_REGISTER Ia32EnergyPerfBiasMsr;
+
+ CpuPmConfig = (POWER_MGMT_CONFIG *) Buffer;
+ Ia32EnergyPerfBiasMsr.Qword = AsmReadMsr64 (MSR_IA32_ENERGY_PERFORMANCE_BIAS);
+ Ia32EnergyPerfBiasMsr.Dwords.Low &= ~B_ENERGY_POLICY_MASK;
+ Ia32EnergyPerfBiasMsr.Dwords.Low |= CpuPmConfig->pTurboSettings->EnergyPolicy;
+ AsmWriteMsr64 (MSR_IA32_ENERGY_PERFORMANCE_BIAS, Ia32EnergyPerfBiasMsr.Qword);
+
+ return EFI_SUCCESS;
+}*/
+//<(AMI_CHG)
+/**
+ Initializes required structures for P-State table creation and enables GV3
+ support in the processor.
+
+ @param[in] FvidPointer Table to update, must be initialized.
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+**/
+VOID
+InitGv3 (
+ IN OUT FVID_TABLE *FvidPointer,
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ )
+{
+ MSR_REGISTER Ia32MiscEnableMsr;
+ EFI_CPUID_REGISTER Cpuid = { 0, 0, 0, 0 };
+
+ ///
+ /// Test for Turbo Mode supported and initialize if true.
+ ///
+ AsmCpuid (CPUID_POWER_MANAGEMENT_PARAMS, &Cpuid.RegEax, &Cpuid.RegEbx, &Cpuid.RegEcx, &Cpuid.RegEdx);
+ Ia32MiscEnableMsr.Qword = AsmReadMsr64 (MSR_IA32_MISC_ENABLE);
+ if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_TURBO) {
+ ///
+ /// Clear Turbo Mode disable bit in IA32 Misc Enable MSR
+ ///
+ Ia32MiscEnableMsr.Qword &= ~B_MSR_IA32_MISC_DISABLE_TURBO;
+ AsmWriteMsr64 (MSR_IA32_MISC_ENABLE, Ia32MiscEnableMsr.Qword);
+ } else if (((Ia32MiscEnableMsr.Qword & B_MSR_IA32_MISC_DISABLE_TURBO) == 0) &&
+ ((Cpuid.RegEax & B_CPUID_POWER_MANAGEMENT_EAX_TURBO) == B_CPUID_POWER_MANAGEMENT_EAX_TURBO)) {
+ ///
+ /// If Turbo mode is supported but required to be disabled (by platform policy setting)
+ /// Set Turbo Mode disable bit in IA32 Misc Enable MSR since it might be temporarily enabled earlier.
+ ///
+ Ia32MiscEnableMsr.Qword |= B_MSR_IA32_MISC_DISABLE_TURBO;
+ AsmWriteMsr64 (MSR_IA32_MISC_ENABLE, Ia32MiscEnableMsr.Qword);
+ }
+
+ ///
+ /// Initialize the FVID tables.
+ ///
+ InitFvidTable (FvidPointer, FVID_MAX_STATES, FVID_MIN_STEP_SIZE, FALSE);
+ ASSERT (FvidPointer->FvidHeader.Gv3States != 0);
+
+ ///
+ /// Enable GV3 on all logical processors.
+ ///
+ RunOnAllLogicalProcessors (ApSafeEnableGv3, NULL);
+
+ return;
+}
+
+/**
+ Enables GV3 support in a logical processor.
+
+ This function must be MP safe.
+
+ @param[in] Buffer Pointer to arguments - not used
+
+ @retval EFI_SUCCESS
+**/
+VOID
+EFIAPI
+ApSafeEnableGv3 (
+ IN OUT VOID *Buffer
+ )
+{
+ MSR_REGISTER Ia32MiscEnable;
+ MSR_REGISTER MiscPwrMgmt;
+
+ ///
+ /// Enable GV3 in the CPU MSR.
+ ///
+ Ia32MiscEnable.Qword = AsmReadMsr64 (MSR_IA32_MISC_ENABLE);
+ Ia32MiscEnable.Qword |= B_MSR_IA32_MISC_ENABLE_EIST;
+ AsmWriteMsr64 (MSR_IA32_MISC_ENABLE, Ia32MiscEnable.Qword);
+
+ ///
+ /// If CMP is disabled, disable hardware coordination.
+ ///
+ if (!(mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_CMP)) {
+ MiscPwrMgmt.Qword = AsmReadMsr64 (MSR_MISC_PWR_MGMT);
+ MiscPwrMgmt.Qword |= B_MSR_MISC_PWR_MGMT_EIST_HW;
+ AsmWriteMsr64 (MSR_MISC_PWR_MGMT, MiscPwrMgmt.Qword);
+ }
+
+ return;
+}
+
+/**
+ Configures the Interrupt Redirection Mode Selection for Logical Interrupts.
+
+ @param[in] CpuPmConfig Pointer to PPM Policy structure.
+**/
+VOID
+InitPpmIrmConfiguration (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ )
+{
+ UINTN PciD0F0RegBase;
+ UINTN MchBar;
+ UINT32 Data32And;
+ UINT32 Data32Or;
+ UINT8 PpmIrmSetting;
+
+ //
+ ///
+ /// HSW BWG Rev 0.6.0, Section 16.4.1 Power Aware Interrupt Routing
+ /// Program Interrupt Routiong Control register MCHBAR+0x5418 as PAIR with Fixed Priority
+ ///
+ PpmIrmSetting = 4;
+ ///
+ /// Get the MCH space base address and program MMIO register MCHBAR+0x5418 to enable specific routing algorithm.
+ ///
+ PciD0F0RegBase = MmPciAddress (0, 0, 0, 0, 0);
+ MchBar = MmioRead32 (PciD0F0RegBase + 0x48) &~BIT0;
+ Data32And = (UINT32) ~(BIT2 + BIT1 + BIT0);
+ Data32Or = (UINT32) (PpmIrmSetting & (BIT2 + BIT1 + BIT0));
+ MmioAndThenOr32 (MchBar + 0x5418, Data32And, Data32Or);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (MchBar + 0x5418),
+ 1,
+ (VOID *) (UINTN) (MchBar + 0x5418)
+ );
+}
+
+/**
+ This function updates the table provided with the FVID data for the processor.
+ If CreateDefaultTable is TRUE, a minimam FVID table will be provided.
+ The maximum number of states must be greater then or equal to two.
+ The table should be initialized in such a way as for the caller to determine if the
+ table was updated successfully. This function should be deprecated in the future when
+ Release 8 is integrated in favor of the EIST protocol calculating FVID information.
+
+ @param[in] FvidPointer Pointer to a table to be updated
+ @param[in] MaxNumberOfStates Number of entries in the table pointed to by FvidPointer
+ @param[in] MinStepSize Minimum step size for generating the FVID table
+ @param[in] CreateDefaultTable Create default FVID table rather then full state support
+**/
+VOID
+InitFvidTable (
+ IN OUT FVID_TABLE *FvidPointer,
+ IN UINT16 MaxNumberOfStates,
+ IN UINT16 MinStepSize,
+ IN BOOLEAN CreateDefaultTable
+ )
+{
+ EFI_STATUS Status;
+
+ ///
+ /// Return the function, if the FVID tables have already been created.
+ ///
+ if (FvidPointer[0].FvidHeader.Gv3States != 0) {
+ return;
+ }
+ ///
+ /// Create FVID table
+ ///
+ if (CreateDefaultTable) {
+ CreateDefaultFvidTable (FvidPointer);
+ mPpmGlobalNvsAreaProtocol->Area->PpmFlags &= ~PPM_TURBO;
+ } else {
+ Status = CreateFvidTable (FvidPointer, MaxNumberOfStates);
+ if (EFI_ERROR (Status)) {
+ CreateDefaultFvidTable (FvidPointer);
+ mPpmGlobalNvsAreaProtocol->Area->PpmFlags &= ~PPM_TURBO;
+ }
+ }
+
+ return;
+}
+
+/**
+ Create default FVID table with max and min states only.
+
+ @param[in] FvidPointer Pointer to a table to be updated
+**/
+VOID
+CreateDefaultFvidTable (
+ IN OUT FVID_TABLE *FvidPointer
+ )
+{
+ UINT64 wPower1;
+ UINT64 wPower2;
+
+ ///
+ /// Fill in the FVid table header.
+ ///
+ FvidPointer[0].FvidHeader.Stepping = mPpmGlobalNvsAreaProtocol->Area->Cpuid;
+ FvidPointer[0].FvidHeader.MaxBusRatio = mMaxBusRatio;
+ FvidPointer[0].FvidHeader.Gv3States = 2;
+ ///
+ /// First entry is state 0, highest state.
+ ///
+ FvidPointer[1].FvidState.State = 0;
+ FvidPointer[1].FvidState.BusRatio = mMaxBusRatio;
+ ///
+ /// Power is calculated in milliwatts
+ ///
+ FvidPointer[1].FvidState.Power = (mPackageTdpWatt * 1000);
+ ///
+ /// Second entry is state 1, lowest state.
+ ///
+ FvidPointer[2].FvidState.State = 1;
+ FvidPointer[2].FvidState.BusRatio = (UINT16) mMinBusRatio;
+ ///
+ /// Calculate Relative Power per HSW BWG (0.6.0 section 13.10.4)
+ ///
+ wPower1 = (mMaxBusRatio - FvidPointer[2].FvidState.BusRatio) * 625;
+ wPower1 = (110000 - wPower1);
+ wPower1 = DivU64x32 (wPower1, 11);
+ wPower1 = DivU64x32 (MultU64x64 (wPower1, wPower1), 1000);
+ //
+ // Power is calculated in milliwatts
+ //
+ wPower2 = (((FvidPointer[2].FvidState.BusRatio * 100000) / mMaxBusRatio) / 100);
+ wPower2 = DivU64x32 (MultU64x32 (MultU64x64 (wPower2, DivU64x32 (wPower1, 100)), mPackageTdpWatt), 1000);
+ FvidPointer[2].FvidState.Power = (UINT16) wPower2;
+}
+
+/**
+ Calculate the ratio for the requested p state based on HSW BWG recommendation
+
+ @param[in] MaxRatio Maximum Supported Ratio (HFM)
+ @param[in] MinRatio Minimum Supported Ratio (LFM)
+ @param[in] MaxNumberOfStates Number of entries in the table pointed to by FvidPointer
+ @param[in] PStateNumber Desired P State from range 0..MaxNumberOfStates
+
+ @retval Ratio for the requested Pstate
+**/
+UINT16
+ComputePstateRatio (
+ IN UINT16 MaxRatio,
+ IN UINT16 MinRatio,
+ IN UINT16 MaxNumberOfStates,
+ IN UINT16 PStateNumber
+ )
+{
+ UINT16 RatioRange;
+ UINT16 NumGaps;
+ UINT16 PStateRatio;
+
+ RatioRange = MaxRatio - MinRatio;
+ NumGaps = MaxNumberOfStates - 1;
+ PStateRatio = MaxRatio - (((PStateNumber * RatioRange) + (NumGaps / 2)) / NumGaps);
+
+ return PStateRatio;
+}
+
+/**
+ Create an FVID table based on the algorithm provided by the HSW BIOS writer's guide.
+
+ @param[in] FvidPointer Pointer to a table to be updated
+ @param[in] MaxNumberOfStates Number of entries in the table pointed to by FvidPointer
+
+ @retval EFI_SUCCESS FVID table created successfully.
+ @retval EFI_INVALID_PARAMETER The bus ratio range don't permit FVID table calculation;
+ a default FVID table should be constructed.
+**/
+EFI_STATUS
+CreateFvidTable (
+ IN OUT FVID_TABLE *FvidPointer,
+ IN UINT16 MaxNumberOfStates
+ )
+{
+ UINT16 BusRatioRange;
+ UINT16 PowerRange;
+ UINT16 NumberOfStates;
+ UINT16 Turbo;
+ UINT16 index;
+ UINT64 wPower1;
+ UINT64 wPower2;
+
+ ///
+ /// Determine the bus ratio range
+ ///
+ BusRatioRange = mMaxBusRatio - mMinBusRatio;
+ if (((INT16) BusRatioRange < 0) || (MaxNumberOfStates == 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ ///
+ /// Determine the Power range
+ ///
+ PowerRange = FVID_MAX_POWER - FVID_MIN_POWER;
+ ///
+ /// Determine the HFM state index
+ ///
+ Turbo = ((mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_TURBO) ? 1 : 0);
+ ///
+ /// Determine the number of states as cpu supported range or Maximum _PSS limit
+ ///
+ NumberOfStates = ((BusRatioRange + 1) < MaxNumberOfStates ? (BusRatioRange + 1) : MaxNumberOfStates);
+ ///
+ /// Ensure we have at least two states
+ ///
+ if ((NumberOfStates + Turbo) < 2) {
+ ///
+ /// In case HFM = LFM and no Turbo, at least have two states with same ratio values
+ ///
+ NumberOfStates = 2;
+ }
+ ///
+ /// Fill in the table header
+ ///
+ FvidPointer[0].FvidHeader.Stepping = mPpmGlobalNvsAreaProtocol->Area->Cpuid;
+ FvidPointer[0].FvidHeader.MaxBusRatio = (Turbo ? mTurboBusRatio : mMaxBusRatio);
+ FvidPointer[0].FvidHeader.Gv3States = (UINT16) (NumberOfStates < MaxNumberOfStates ? (NumberOfStates + Turbo) : NumberOfStates);
+ ///
+ /// Add Turbo as P0 if Turbo Mode supported and initialize.
+ ///
+ if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_TURBO) {
+ FvidPointer[1].FvidState.BusRatio = mTurboBusRatio;
+ FvidPointer[1].FvidState.Power = (mPackageTdpWatt * 1000); // power is calculated in milliwatts
+ ///
+ /// Reserve on P-State for Max Turbo
+ ///
+ if (NumberOfStates == MaxNumberOfStates) {
+ NumberOfStates--;
+ }
+ }
+ ///
+ /// Add HFM as P0 or P1 based on Max Turbo availablity
+ ///
+ FvidPointer[1 + Turbo].FvidState.State = Turbo;
+ FvidPointer[1 + Turbo].FvidState.BusRatio = mMaxBusRatio;
+ //
+ // Power is calculated in milliwatts
+ //
+ FvidPointer[1 + Turbo].FvidState.Power = (mPackageTdpWatt * 1000);
+ ///
+ /// Fill in the table starting at the last entry
+ /// The algorithm is available in the processor BIOS writer's guide.
+ ///
+ for (index = 1; index < NumberOfStates; index++) {
+ FvidPointer[index + 1 + Turbo].FvidState.State = index + Turbo;
+ FvidPointer[index + 1 + Turbo].FvidState.BusRatio = ComputePstateRatio (mMaxBusRatio, mMinBusRatio, NumberOfStates, index);
+ ///
+ /// Calculate Relative Power per HSW BWG
+ ///
+ wPower1 = (mMaxBusRatio - FvidPointer[index + 1 + Turbo].FvidState.BusRatio) * 625;
+ wPower1 = (110000 - wPower1);
+ wPower1 = DivU64x32 (wPower1, 11);
+ wPower1 = MultU64x64 (wPower1, wPower1);
+ ///
+ /// Power is calculated in milliwatts
+ ///
+ wPower2 = (((FvidPointer[index + 1 + Turbo].FvidState.BusRatio * 100) / mMaxBusRatio));
+ wPower2 = DivU64x32 (MultU64x32 (MultU64x64 (wPower2, wPower1), mPackageTdpWatt), 10000000);
+ FvidPointer[index + 1 + Turbo].FvidState.Power = (UINT32) wPower2;
+ ///
+ /// For Controllable Tdp -- Configure PPC as LFM (i.e fake LFM + 1)
+ ///
+ if (mControllableTdpEnable == 1 && FvidPointer[index + 1 + Turbo].FvidState.BusRatio == (mMinBusRatio + 1)) {
+ mPpmGlobalNvsAreaProtocol->Area->ConfigurablePpc = (UINT8)FvidPointer[index + 1 + Turbo].FvidState.State;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set processor P state to HFM or LFM.
+
+ @exception EFI_UNSUPPORTED EIST not supported.
+ @retval EFI_SUCCESS Processor P state has been set.
+**/
+VOID
+SetBootPState (
+ VOID
+ )
+{
+ MSR_REGISTER Ia32MiscEnable;
+ MSR_REGISTER Ia32PerfCtl;
+ BOOLEAN EistEnabled;
+
+ ///
+ /// This function will be executed even when EIST is disabled so processor can be switched to HFM
+ /// Only skip this when EIST is not capable.
+ ///
+ if ((mCpuid01.RegEcx & B_CPUID_VERSION_INFO_ECX_EIST) == 0) {
+ return;
+ }
+ ///
+ /// Read EIST.
+ ///
+ Ia32MiscEnable.Qword = AsmReadMsr64 (MSR_IA32_MISC_ENABLE);
+ EistEnabled = (BOOLEAN) RShiftU64 (
+ (Ia32MiscEnable.Qword & B_MSR_IA32_MISC_ENABLE_EIST),
+ N_MSR_IA32_MISC_ENABLE_EIST_OFFSET
+ );
+ ///
+ /// If EIST is disabled, temporarily enable it
+ ///
+ if (EistEnabled == 0) {
+ Ia32MiscEnable.Qword |= B_MSR_IA32_MISC_ENABLE_EIST;
+ AsmWriteMsr64 (MSR_IA32_MISC_ENABLE, Ia32MiscEnable.Qword);
+ }
+ Ia32PerfCtl.Qword = AsmReadMsr64 (MSR_IA32_PERF_CTRL);
+ Ia32PerfCtl.Qword &= B_IA32_PERF_CTRLP_STATE_TARGET;
+ mBspBootRatio = (UINT16) RShiftU64 (Ia32PerfCtl.Qword, N_IA32_PERF_CTRLP_STATE_TARGET);
+ ///
+ /// Set P-state on all cores
+ ///
+ RunOnAllLogicalProcessors (ApSafeSetBootPState, NULL);
+ ///
+ /// Disable EIST if we enabled it previously
+ ///
+ if (EistEnabled == 0) {
+ Ia32MiscEnable.Qword = AsmReadMsr64 (MSR_IA32_MISC_ENABLE);
+ Ia32MiscEnable.Qword &= ~B_MSR_IA32_MISC_ENABLE_EIST;
+ AsmWriteMsr64 (MSR_IA32_MISC_ENABLE, Ia32MiscEnable.Qword);
+ }
+
+ return;
+}
+
+/**
+ Set processor P state based on Boot ConfigTdp level.
+
+ @param[in] Buffer Unused
+
+ @retval EFI_SUCCESS Processor MSR setting is saved.
+**/
+VOID
+EFIAPI
+ApSafeSetBootPState (
+ IN OUT VOID *Buffer
+ )
+{
+ MSR_REGISTER Ia32PerfCtl;
+ UINT16 BootRatio;
+
+ Ia32PerfCtl.Qword = AsmReadMsr64 (MSR_IA32_PERF_CTRL);
+ Ia32PerfCtl.Qword &= ~B_IA32_PERF_CTRLP_STATE_TARGET;
+ /*AMI_CHG+>
+ if (mCpuConfigTdpBootRatio != 0) {
+ ///
+ /// For ConfigTDP enabled SKU use (ConfigTDP boot ratio - 1 / TAR Ratio) as max non-turbo ratio
+ ///
+ BootRatio = mCpuConfigTdpBootRatio-1;
+ //
+ // If EIST is disabled use boot ratio ConfigTDP boot ratio / TAR+1.
+ //
+ if((mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_EIST)== 0) {
+ BootRatio = mCpuConfigTdpBootRatio;
+ }
+ } else {
+ ///
+ /// For Non-ConfigTDP enabled SKU set BSP ratio on all threads.
+ ///
+ BootRatio = mBspBootRatio;
+ }<AMI_CHG*/
+ BootRatio = mBspBootRatio;
+ Ia32PerfCtl.Qword |= LShiftU64 (BootRatio, N_IA32_PERF_CTRLP_STATE_TARGET);
+ AsmWriteMsr64 (MSR_IA32_PERF_CTRL, Ia32PerfCtl.Qword);
+
+ return;
+}
+
+//
+// Update ACPI PerfomanceStates tables
+//
+
+/**
+ Patch the native _PSS package with the GV3 values
+ Uses ratio/VID values from the FVID table to fix up the control values in the _PSS.
+
+ (1) Find _PSS package:
+ (1.1) Find the _PR_CPU0 scope.
+ (1.2) Save a pointer to the package length.
+ (1.3) Find the _PSS AML name object.
+ (2) Resize the _PSS package.
+ (3) Fix up the _PSS package entries
+ (3.1) Check Turbo mode support.
+ (3.2) Check Dynamic FSB support.
+ (4) Fix up the Processor block and \_PR_CPU0 Scope length.
+ (5) Update SSDT Header with new length.
+
+ @retval EFI_SUCCESS - on success
+ @retval EFI_NOT_FOUND - if _PR_.CPU0 scope is not foud in the ACPI tables
+**/
+EFI_STATUS
+AcpiPatchPss (
+ VOID
+ )
+{
+ UINT8 *CurrPtr;
+ UINT8 *EndOfTable;
+ UINT8 index;
+ UINT16 NewPackageLength;
+ UINT16 MaxPackageLength;
+ UINT16 Temp;
+ UINT16 *PackageLength;
+ UINT16 *ScopePackageLengthPtr;
+ UINT32 *Signature;
+ PSS_PACKAGE_LAYOUT *PssPackage;
+ MSR_REGISTER TempMsr;
+ UINT16 MaximumEfficiencyRatio;
+ UINT16 MaximumNonTurboRatio;
+ UINT16 PnPercent;
+
+ ScopePackageLengthPtr = NULL;
+ PssPackage = NULL;
+
+ //
+ // Get Maximum Efficiency bus ratio (LFM) from Platform Info MSR Bits[47:40]
+ // Get Maximum Non Turbo bus ratio from Platform Info MSR Bits[15:8]
+ //
+ TempMsr.Qword = AsmReadMsr64 (MSR_PLATFORM_INFO);
+ MaximumEfficiencyRatio = TempMsr.Bytes.SixthByte;
+ MaximumNonTurboRatio = TempMsr.Bytes.SecondByte;
+
+ ///
+ /// Calculate new package length
+ ///
+ NewPackageLength = Temp = (UINT16) (mNumberOfStates * sizeof (PSS_PACKAGE_LAYOUT) + 3);
+ MaxPackageLength = (UINT16) (FVID_MAX_STATES * sizeof (PSS_PACKAGE_LAYOUT) + 3);
+ ///
+ /// Locate the SSDT package in the IST table
+ ///
+ CurrPtr = (UINT8 *) mCpu0IstTable;
+ EndOfTable = (UINT8 *) (CurrPtr + mCpu0IstTable->Length);
+ for (CurrPtr; CurrPtr <= EndOfTable; CurrPtr++) {
+ Signature = (UINT32 *) (CurrPtr + 1);
+ ///
+ /// If we find the _PR_CPU0 scope, save a pointer to the package length
+ ///
+ if ((*CurrPtr == AML_SCOPE_OP) &&
+ (*(Signature + 1) == EFI_SIGNATURE_32 ('_', 'P', 'R', '_')) &&
+ (*(Signature + 2) == EFI_SIGNATURE_32 ('C', 'P', 'U', '0'))
+ ) {
+ ScopePackageLengthPtr = (UINT16 *) (CurrPtr + 1);
+ }
+ ///
+ /// Patch the native _PSS package with the GV3 values
+ ///
+ if ((*CurrPtr == AML_NAME_OP) && (*Signature == EFI_SIGNATURE_32 ('_', 'P', 'S', 'S'))) {
+ ///
+ /// Check table dimensions.
+ /// PSS package reserve space for FVID_MAX_STATES number of P-states so check if the
+ /// current number of P- states is more than FVID_MAX_STATES. Also need to update the SSDT contents
+ /// if the current number of P-states is less than FVID_MAX_STATES.
+ ///
+ ASSERT (mNumberOfStates <= FVID_MAX_STATES);
+ if (mNumberOfStates <= FVID_MAX_STATES) {
+ *(CurrPtr + 8) = (UINT8) mNumberOfStates;
+ PackageLength = (UINT16 *) (CurrPtr + 6);
+ ///
+ /// Update the Package length in AML package length format
+ ///
+ *PackageLength = ((NewPackageLength & 0x0F) | 0x40) | ((Temp << 4) & 0x0FF00);
+ ///
+ /// Move SSDT contents
+ ///
+ CopyMem (
+ (CurrPtr + NewPackageLength),
+ (CurrPtr + MaxPackageLength),
+ EndOfTable - (CurrPtr + MaxPackageLength)
+ );
+ ///
+ /// Save the new end of the SSDT
+ ///
+ EndOfTable = EndOfTable - (MaxPackageLength - NewPackageLength);
+ }
+ PssPackage = (PSS_PACKAGE_LAYOUT *) (CurrPtr + 9);
+ for (index = 1; index <= mNumberOfStates; index++) {
+ ///
+ /// Update the _PSS table
+ ///
+ ///
+ /// If Turbo mode is supported, add one to the Max Non-Turbo frequency
+ ///
+ if ((mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_TURBO) && (index == 1)) {
+ PssPackage->CoreFrequency = (UINT32)((mFvidPointer[index + 1].FvidState.BusRatio)* 100)+1;
+ }else if (mFvidPointer[index].FvidState.BusRatio < MaximumEfficiencyRatio) {
+ //
+ // If cTDP Down Ratio == LFM, set it to 1% lower than LFM.
+ //
+ PnPercent = (MaximumEfficiencyRatio * 100) / MaximumNonTurboRatio;
+ PssPackage->CoreFrequency = (MaximumNonTurboRatio * (PnPercent - 1)); // Simplified Calculation.
+ } else {
+ PssPackage->CoreFrequency = (UINT32)(mFvidPointer[index].FvidState.BusRatio) * 100;
+ }
+ PssPackage->Power = (UINT32) mFvidPointer[index].FvidState.Power;
+ ///
+ /// If it's PSS table, Control is the PERF_CTL value.
+ /// Status entry is the same as control entry.
+ /// TransLatency uses 10
+ ///
+ PssPackage->TransLatency = NATIVE_PSTATE_LATENCY;
+ PssPackage->Control = (UINT32) LShiftU64 (mFvidPointer[index].FvidState.BusRatio, 8);
+ //
+ // Ensure any future OS would not look for the IA32_PERF_STATUS MSR to check if the value matches
+ //
+ if (mFvidPointer[index].FvidState.BusRatio < MaximumEfficiencyRatio) {
+ PssPackage->Status = (UINT32) LShiftU64 (MaximumEfficiencyRatio, 8);
+ } else {
+ PssPackage->Status = (UINT32) LShiftU64 (mFvidPointer[index].FvidState.BusRatio, 8);
+ }
+ PssPackage->BMLatency = PSTATE_BM_LATENCY;
+ PssPackage++;
+ }
+ }
+ }
+ ASSERT (ScopePackageLengthPtr != NULL);
+ if (ScopePackageLengthPtr == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ ///
+ /// Update the Package length in AML package length format
+ ///
+ CurrPtr = (UINT8 *) ScopePackageLengthPtr;
+ NewPackageLength = Temp = (UINT16) (EndOfTable - CurrPtr);
+ *ScopePackageLengthPtr = ((NewPackageLength & 0x0F) | 0x40) | ((Temp << 4) & 0x0FF00);
+ mCpu0IstTable->Length = (UINT32) (EndOfTable - (UINT8 *) mCpu0IstTable);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Completes processor power management initialization
+ (1) Initializes the TSC update variables.
+ (2) Initializes the GV state for processors.
+ (3) Adds a callback (SMI) in S3 resume script to restore the MSR
+ (4) Registers callback (SMI) for late PPM Initialization
+**/
+VOID
+PpmPostInit (
+ VOID
+ )
+{
+ UINT8 Data8;
+
+ ///
+ /// Set Boot P-state based on Policy.
+ ///
+ SetBootPState ();
+ ///
+ /// Save the SW SMI number to trigger SMI to restore the MSRs when resuming from S3
+ ///
+ Data8 = mCpuPmConfig->S3RestoreMsrSwSmiNumber;
+ SCRIPT_IO_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint8,
+ (UINTN) (R_PCH_APM_CNT),
+ 1,
+ &Data8
+ );
+ ///
+ /// Lock down all settings
+ ///
+ PpmLockDown (mCpuPmConfig);
+} \ No newline at end of file
diff --git a/ReferenceCode/Haswell/PowerManagement/Dxe/PowerLimits.c b/ReferenceCode/Haswell/PowerManagement/Dxe/PowerLimits.c
new file mode 100644
index 0000000..9c0c19e
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/Dxe/PowerLimits.c
@@ -0,0 +1,1302 @@
+/** @file
+ This file contains power management configuration functions for
+ Haswell processors.
+
+ Acronyms:
+ PPM - Processor Power Management
+ TM - Thermal Monitor
+ IST - Intel(R) Speedstep technology
+ HT - Hyper-Threading Technology
+
+@copyright
+ Copyright (c) 2012 - 2014 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
+
+**/
+#include "PowerMgmtCommon.h"
+
+PPM_CTDP_OVERRIDE_TABLE mHswUltPpmCtdpOverideTable[]={
+/// TDP Icc MSR PL1 MSR PL2 TdpUp TdpUp TdpNominal TdpNominal TdpDown TdpDown
+/// Max PL1 PL2 PL1 PL2 PL1 PL2
+ { 5700, 0, 6700, 8375, 0, 8375, 0, 8375, 0, 8375 }, /// 57W Sku Overrides
+ { 1500, 0, 2500, 2500, 0, 2500, 0, 2500, 0, 2500 }, /// 15W Sku Overrides
+ { 1150, 0, 0, 2500, 0, 2500, 0, 2500, 0, 2500 }, /// 11.5W Sku Overrides
+ { 2800, 40, 0, 3500, 0, 3500, 0, 3500, 0, 3500 } /// 28W 40A Sku Overrides
+};
+
+PPM_CTRL_TDP_SKU_TBL mHswCtrlTdpSkuTable[] = {
+ {"Celeron",03,{"2955U","2957U","2005U"}}
+};
+
+/**
+ Configurable TDP BIOS Initialization
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+ @param[in] FvidPointer Pointer to Fvid Table
+
+ @exception EFI_UNSUPPORTED Ctdp not Supported
+ @retval EFI_SUCCESS Ctdp Initiation done
+**/
+EFI_STATUS
+InitializeConfigurableTdp (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS CustomCtdpSettings;
+ UINTN Index;
+
+
+ if (mPpmGlobalNvsAreaProtocol == NULL) {
+ DEBUG ((EFI_D_INFO, "PPM:: ConfigTDP Require mPpmGlobalNvsAreaProtocol.\n"));
+ return EFI_UNSUPPORTED;
+ }
+ ///
+ /// Intialize PPM Global NVS with custom CTDP level settings or CPU provided.
+ ///
+ CustomCtdpSettings = InitCustomConfigurableTdp (CpuPmConfig);
+ if (CustomCtdpSettings != EFI_SUCCESS) {
+ Status = InitConfigurableTdpSettings (CpuPmConfig);
+ if (Status != EFI_SUCCESS) {
+ ///
+ /// Check for Controllable TDP enable if Ctdp not supported
+ ///
+ InitControllableTdp(CpuPmConfig);
+ return EFI_UNSUPPORTED;
+ }
+ }
+ ///
+ /// In case of LFM == TDP Down Ratio/Tdp Nominal , consider TDP Down TAR as the new LFM to insert fake P state.
+ ///
+ for (Index = 0; Index < (mPpmGlobalNvsAreaProtocol->Area->CtdpLevelsSupported); Index++) {
+ if (mMinBusRatio == mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[Index].CtdpTar+1) {
+ mMinBusRatio = mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[Index].CtdpTar;
+ DEBUG ((EFI_D_INFO, "PPM:: mMinBusRatio Modified for Ctdp %d\n", mMinBusRatio));
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Custom Configurable TDP Table BIOS Initialization
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+
+ @exception EFI_UNSUPPORTED Custom Ctdp settings are not available
+ @retval EFI_SUCCESS Successfully Initialized Custom Ctdp Settings
+**/
+EFI_STATUS
+InitCustomConfigurableTdp (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ )
+{
+ UINT8 Index;
+
+ if (!CpuPmConfig->pCustomCtdpSettings->ConfigTdpCustom) {
+ return EFI_UNSUPPORTED;
+ }
+ ///
+ /// CTC value should not be more Custom configured levels.
+ ///
+ if (CpuPmConfig->pCustomCtdpSettings->CustomBootModeIndex > CpuPmConfig->pCustomCtdpSettings->CustomTdpCount - 1) {
+ CpuPmConfig->pCustomCtdpSettings->CustomBootModeIndex = 0;
+ }
+ if (mPpmGlobalNvsAreaProtocol != NULL) {
+ ///
+ /// Update Custom ConfigTdp table for ACPI
+ ///
+ if (CpuPmConfig->pCustomCtdpSettings->CustomTdpCount != 0) {
+ mPpmGlobalNvsAreaProtocol->Area->CustomConfigTdp = PPM_ENABLE;
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelsSupported = CpuPmConfig->pCustomCtdpSettings->CustomTdpCount;
+ mPpmGlobalNvsAreaProtocol->Area->ConfigTdpBootModeIndex = CpuPmConfig->pCustomCtdpSettings->CustomBootModeIndex;
+ for (Index = 0; Index < (CpuPmConfig->pCustomCtdpSettings->CustomTdpCount); Index++) {
+ ///
+ /// Verify and fix Custom configured CTDP Levels PL1 and PL2
+ ///
+ CpuPmConfig->pCustomCtdpSettings->CustomConfigTdpTable[Index].CustomPowerLimit1 = VerifyAndFixCustomPowerLimit (CpuPmConfig->pCustomCtdpSettings->CustomConfigTdpTable[Index].CustomPowerLimit1,mCustomPowerUnit);
+ CpuPmConfig->pCustomCtdpSettings->CustomConfigTdpTable[Index].CustomPowerLimit2 = VerifyAndFixCustomPowerLimit (CpuPmConfig->pCustomCtdpSettings->CustomConfigTdpTable[Index].CustomPowerLimit2,mCustomPowerUnit);
+ CpuPmConfig->pCustomCtdpSettings->CustomConfigTdpTable[Index].CustomTurboActivationRatio = VerifyAndFixCustomRatio (CpuPmConfig->pCustomCtdpSettings->CustomConfigTdpTable[Index].CustomTurboActivationRatio+1)-1;
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[Index].CtdpPowerLimit1 = (UINT16) CpuPmConfig->pCustomCtdpSettings->CustomConfigTdpTable[Index].CustomPowerLimit1;
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[Index].CtdpPowerLimit2 = (UINT16) CpuPmConfig->pCustomCtdpSettings->CustomConfigTdpTable[Index].CustomPowerLimit2;
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[Index].CtdpPowerLimitWindow = CpuPmConfig->pCustomCtdpSettings->CustomConfigTdpTable[Index].CustomPowerLimit1Time;
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[Index].CtdpTar = CpuPmConfig->pCustomCtdpSettings->CustomConfigTdpTable[Index].CustomTurboActivationRatio;
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[Index].CtdpCtc = CpuPmConfig->pCustomCtdpSettings->CustomConfigTdpTable[Index].CustomConfigTdpControl;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Verify and fix Custom Power Limit values
+
+ @param[in] CustomPowerLimit Custom Power Limit value
+ @param[in] CustomPlUnit Custom Power Limit Unit
+**/
+UINT16
+VerifyAndFixCustomPowerLimit (
+ IN UINT32 CustomPowerLimit,
+ IN UINT16 CustomPlUnit
+ )
+{
+ UINT16 ConvertedPowerLimit;
+ UINT16 CpuConvertedPowerLimitMaxLimit;
+
+ ConvertedPowerLimit = (UINT16) ((CustomPowerLimit * mProcessorPowerUnit) / CustomPlUnit);
+ if (mPackageMaxPower == 0 && ConvertedPowerLimit >= mPackageMinPower) {
+ ///
+ /// If PACKAGE_POWER_SKU_MSR [46:32] = 0 means there is no upper limit ( since this field is 15 bits, the max value is 2^15 - 1 )
+ ///
+ CpuConvertedPowerLimitMaxLimit = (UINT16) (LShiftU64 (2, 15) - 1);
+ if (ConvertedPowerLimit > CpuConvertedPowerLimitMaxLimit) {
+ ///
+ /// If new Power Limit 1 is > CpuConvertedPowerLimit1MaxLimit, program Power Limit 1 to CpuConvertedPowerLimit1MaxLimit
+ ///
+ ConvertedPowerLimit = CpuConvertedPowerLimitMaxLimit;
+ }
+ } else if (mPackageMinPower == 0 && ConvertedPowerLimit > 0 && ConvertedPowerLimit <= mPackageMaxPower) {
+ ///
+ /// If PACKAGE_POWER_SKU_MSR [30:16] = 0 means there is no lower limit
+ ///
+ ConvertedPowerLimit = (UINT16) ((CustomPowerLimit * mProcessorPowerUnit) / CustomPlUnit);
+ } else {
+ ///
+ /// Power Limit 1 needs to be between mPackageMinPower and mPackageMaxPower
+ ///
+ CpuConvertedPowerLimitMaxLimit = mPackageMaxPower;
+ if (ConvertedPowerLimit < mPackageMinPower) {
+ ///
+ /// If new Power Limit 1 is < mPackageMinPower, program Power Limit 1 to mPackageMinPower
+ ///
+ ConvertedPowerLimit = mPackageMinPower;
+ } else if (ConvertedPowerLimit > CpuConvertedPowerLimitMaxLimit) {
+ ///
+ /// If new Power Limit 1 is > mPackageMaxPower, program Power Limit 1 to mPackageMaxPower
+ ///
+ ConvertedPowerLimit = CpuConvertedPowerLimitMaxLimit;
+ }
+ }
+
+ return ConvertedPowerLimit;
+}
+
+/**
+ Verify and fix Custom Ratio values
+ Custom Ratio should be between MaxTurboFrequency and LFM
+
+ @param[in] CustomRatio Custom Ratio value
+**/
+UINT8
+VerifyAndFixCustomRatio (
+ IN UINT8 CustomRatio
+ )
+{
+ if (CustomRatio > mTurboBusRatio) {
+ ///
+ /// Use HFM as max value if Turbo is not supported
+ ///
+ if (mTurboBusRatio == 0) {
+ CustomRatio = (UINT8) mMaxBusRatio;
+ } else {
+ CustomRatio = (UINT8) mTurboBusRatio;
+ }
+ } else if (CustomRatio < mMinBusRatio) {
+ ///
+ /// Use LFM as min value
+ ///
+ CustomRatio = (UINT8) mMinBusRatio;
+ }
+
+ return CustomRatio;
+}
+
+/**
+ CTDP BIOS settings Initialization(From Msrs)
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+
+ @exception EFI_UNSUPPORTED Ctdp not supported
+ @retval EFI_SUCCESS Ctdp Settings Initialized successfully from MSRs
+**/
+EFI_STATUS
+InitConfigurableTdpSettings (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ )
+{
+ MSR_REGISTER TempMsr;
+ UINTN Index;
+ UINT16 CpuConfigTdpNominalTdp;
+ UINT16 CpuConfigTdpLevel1Tdp;
+ UINT16 CpuConfigTdpLevel2Tdp;
+ UINT8 CpuConfigTdpNominalRatio;
+ UINT8 CpuConfigTdpLevel1Ratio;
+ UINT8 CpuConfigTdpLevel2Ratio;
+ UINT16 CpuConfigTdpLevels;
+
+ ///
+ /// Get the number of configurable TDP Levels supported
+ ///
+ TempMsr.Qword = AsmReadMsr64 (MSR_PLATFORM_INFO);
+ TempMsr.Qword &= V_CONFIG_TDP_NUM_LEVELS_MASK;
+ CpuConfigTdpLevels = (UINT8) RShiftU64 (TempMsr.Qword, N_MSR_PLATFORM_INFO_CONFIG_TDP_NUM_LEVELS_OFFSET);
+ DEBUG ((EFI_D_INFO, "PPM:: ConfigTDP Supported Levels=%d\n", CpuConfigTdpLevels));
+ ///
+ /// Return if ConfigTDP Levels not supported
+ ///
+ if (CpuConfigTdpLevels == 0) {
+ DEBUG ((EFI_D_INFO, "PPM:: ConfigTDP Levels not supported\n"));
+ return EFI_UNSUPPORTED;
+ }
+ mPpmGlobalNvsAreaProtocol->Area->CustomConfigTdp = PPM_DISABLE;
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelsSupported = (UINT8) CpuConfigTdpLevels + 1;
+ mPpmGlobalNvsAreaProtocol->Area->ConfigTdpBootModeIndex = CpuPmConfig->pTurboSettings->ConfigTdpLevel;
+ ///
+ /// Get PKG_TDP for Config TDP Nominal
+ ///
+ TempMsr.Qword = AsmReadMsr64 (MSR_CONFIG_TDP_NOMINAL);
+ CpuConfigTdpNominalRatio = (UINT8) (TempMsr.Dwords.Low & CONFIG_TDP_NOMINAL_RATIO_MASK);
+ CpuConfigTdpNominalTdp = mPackageTdp;
+ DEBUG ((EFI_D_INFO, "PPM:: ConfigTDP Nominal Ratio=%d Tdp=%d\n", CpuConfigTdpNominalRatio, CpuConfigTdpNominalTdp));
+ ///
+ /// Set Level0 as Tdp Nominal
+ ///
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[0].CtdpPowerLimit1 = mPackageTdp;
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[0].CtdpPowerLimit2 = GetCtdpPowerLimit2 (mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[0].CtdpPowerLimit1);
+ if (IS_SA_DEVICE_ID_MOBILE(mProcessorFlavor)) {
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[0].CtdpPowerLimitWindow = MB_POWER_LIMIT1_TIME_DEFAULT;
+ } else {
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[0].CtdpPowerLimitWindow = DT_POWER_LIMIT1_TIME_DEFAULT;
+ }
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[0].CtdpTar = (UINT8) (CpuConfigTdpNominalRatio - 1);
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[0].CtdpCtc = CONFIG_TDP_NOMINAL;
+ ///
+ /// Get PKG_TDP and Ratio for Config TDP Level1
+ ///
+ TempMsr.Qword = AsmReadMsr64 (MSR_CONFIG_TDP_LVL1);
+ CpuConfigTdpLevel1Ratio = (UINT8) RShiftU64 (
+ TempMsr.Qword & CONFIG_TDP_LVL1_RATIO_MASK,
+ CONFIG_TDP_LVL1_RATIO_OFFSET
+ );
+ CpuConfigTdpLevel1Tdp = (UINT16) (TempMsr.Dwords.Low & CONFIG_TDP_LVL1_PKG_TDP_MASK);
+ DEBUG ((EFI_D_INFO, "PPM:: ConfigTDP Level1 Ratio=%d Tdp=%d\n", CpuConfigTdpLevel1Ratio, CpuConfigTdpLevel1Tdp));
+ ///
+ /// Set Level 1
+ ///
+ Index = 1;
+ if (CpuConfigTdpLevel1Ratio != 0) {
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[Index].CtdpPowerLimit1 = CpuConfigTdpLevel1Tdp;
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[Index].CtdpPowerLimit2 = GetCtdpPowerLimit2 (mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[Index].CtdpPowerLimit1);
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[Index].CtdpPowerLimitWindow = mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[0].CtdpPowerLimitWindow;
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[Index].CtdpTar = (UINT8) (CpuConfigTdpLevel1Ratio - 1);
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[Index].CtdpCtc = CONFIG_TDP_LEVEL1;
+ Index++;
+ }
+ ///
+ /// If two levels are supported or Level1 was not valid
+ /// then read Level2 registers
+ ///
+ if (CpuConfigTdpLevels == CONFIG_TDP_LEVEL2 || CpuConfigTdpLevel1Ratio == 0) {
+ ///
+ /// Get PKG_TDP and Ratio for Config TDP Level2
+ ///
+ TempMsr.Qword = AsmReadMsr64 (MSR_CONFIG_TDP_LVL2);
+ CpuConfigTdpLevel2Ratio = (UINT8) RShiftU64 (
+ TempMsr.Qword & CONFIG_TDP_LVL2_RATIO_MASK,
+ CONFIG_TDP_LVL2_RATIO_OFFSET
+ );
+ CpuConfigTdpLevel2Tdp = (UINT16) (TempMsr.Dwords.Low & CONFIG_TDP_LVL2_PKG_TDP_MASK);
+ DEBUG ((EFI_D_INFO, "PPM:: ConfigTDP Level2 Ratio=%d Tdp=%d\n", CpuConfigTdpLevel2Ratio, CpuConfigTdpLevel2Tdp));
+ ///
+ /// Set Level2
+ ///
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[Index].CtdpPowerLimit1 = CpuConfigTdpLevel2Tdp;
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[Index].CtdpPowerLimit2 = GetCtdpPowerLimit2 (mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[Index].CtdpPowerLimit1);
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[Index].CtdpPowerLimitWindow = mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[0].CtdpPowerLimitWindow;
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[Index].CtdpTar = (UINT8) (CpuConfigTdpLevel2Ratio - 1);
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[Index].CtdpCtc = CONFIG_TDP_LEVEL2;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get Power Limit2 based on Power Limit1 on Config TDP
+
+ @param[in] PowerLimit1 Power Limit 1 Value
+
+ @retval Calculated Power Limit2 value
+**/
+UINT16
+GetCtdpPowerLimit2 (
+ IN UINT16 PowerLimit1
+ )
+{
+ UINT16 ConvertedPowerLimit2;
+ UINT16 Mutliplier;
+
+ ///
+ /// By default,for Mobile & Desktop Processors: Short duration Power Limit = 1.25 * Package TDP
+ ///
+ Mutliplier = 125;
+ ///
+ /// For XE/non-ULV skus Configure PL2 as (1.25 x cTDP).
+ ///
+ ConvertedPowerLimit2 = EFI_IDIV_ROUND ((Mutliplier * PowerLimit1), 100);
+
+ return ConvertedPowerLimit2;
+}
+
+/**
+ Patch Fvid Table with Ctdp Tar ratio and Tar-1 Ratio
+
+ @param[in] FvidPointer Pointer to Fvid Table
+**/
+VOID
+CtdpPatchFvidTable (
+ IN OUT FVID_TABLE *FvidPointer
+ )
+{
+ UINTN PssIndex;
+ UINTN Index;
+ UINTN TempRatio;
+ UINT8 Turbo;
+
+ ///
+ /// Check P0 is Turbo Ratio or HFM
+ ///
+ Turbo = ((mPpmGlobalNvsAreaProtocol->Area->PpmFlags & PPM_TURBO) ? 1 : 0);
+
+ ///
+ /// Check and patch Fvid table for TAR ratios
+ ///
+ for (Index = 0; Index < mPpmGlobalNvsAreaProtocol->Area->CtdpLevelsSupported; Index++) {
+ TempRatio = mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[Index].CtdpTar;
+ for (PssIndex = (Turbo + 2); PssIndex < FvidPointer[0].FvidHeader.Gv3States; PssIndex++) {
+ if (FvidPointer[PssIndex].FvidState.BusRatio < TempRatio) {
+ if (FvidPointer[PssIndex - 1].FvidState.BusRatio != TempRatio) {
+ ///
+ /// If Tar not Found ,Replace Turbo Active ratio at PssIndex-1
+ /// P0 - Turbo ratio P1- HFM ,exclude these two ratios
+ ///
+ if (PssIndex == (Turbo + 2)) {
+ CtdpReplaceFvidRatio (FvidPointer, PssIndex, TempRatio);
+ DEBUG ((EFI_D_INFO, " TAR Ratio Replace at %x with %x \n", PssIndex, TempRatio));
+ } else {
+ CtdpReplaceFvidRatio (FvidPointer, PssIndex - 1, TempRatio);
+ DEBUG ((EFI_D_INFO, " TAR Ratio Replace at %x with %x \n", PssIndex-1, TempRatio));
+
+ }
+ }
+ break;
+ }
+ }
+ }
+ ///
+ /// Check and patch Fvid table for CTDP ratios.
+ /// This is done separately to make sure Ctdp ratios are not override by Tar ratios
+ /// when ctdp ratios are adjacent
+ ///
+ for (Index = 0; Index < mPpmGlobalNvsAreaProtocol->Area->CtdpLevelsSupported; Index++) {
+ TempRatio = mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[Index].CtdpTar + 1;
+ for (PssIndex = (Turbo + 1); PssIndex < FvidPointer[0].FvidHeader.Gv3States; PssIndex++) {
+
+ if (FvidPointer[PssIndex].FvidState.BusRatio == TempRatio) {
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[Index].CtdpPpc = (UINT8) FvidPointer[PssIndex].FvidState.State;
+ }
+
+ if (FvidPointer[PssIndex].FvidState.BusRatio < TempRatio) {
+ if (FvidPointer[PssIndex - 1].FvidState.BusRatio == TempRatio) {
+ ///
+ /// Found Turbo Active ratio at PssIndex-1
+ ///
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[Index].CtdpPpc = (UINT8) FvidPointer[PssIndex - 1].FvidState.State;
+ break;
+ } else {
+ ///
+ /// If Tar not Found, Replace Turbo Active ratio at PssIndex-1
+ ///
+ if(PssIndex == (Turbo + 1)) {
+ CtdpReplaceFvidRatio (FvidPointer, PssIndex, TempRatio);
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[Index].CtdpPpc = (UINT8) FvidPointer[PssIndex].FvidState.State;
+ DEBUG ((EFI_D_INFO, " CTDP Ratio Replace at %x with %x \n", PssIndex, TempRatio));
+ } else {
+ CtdpReplaceFvidRatio (FvidPointer, PssIndex - 1, TempRatio);
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[Index].CtdpPpc = (UINT8) FvidPointer[PssIndex - 1].FvidState.State;
+ DEBUG ((EFI_D_INFO, " CTDP Ratio Replace at %x with %x \n", PssIndex-1, TempRatio));
+
+ }
+ break;
+ }
+ }
+ }
+ }
+}
+
+/**
+ Replace P state with given ratio
+
+ @param[in] FvidPointer Pointer to Fvid Table
+ @param[in] PssIndex FVID table index of P state to be replaced
+ @param[in] Ratio Target Ratio to put in
+**/
+VOID
+CtdpReplaceFvidRatio (
+ IN OUT FVID_TABLE *FvidPointer,
+ UINTN PssIndex,
+ UINTN Ratio
+ )
+{
+ UINT64 wPower1;
+ UINT64 wPower2;
+
+ FvidPointer[PssIndex].FvidState.BusRatio = (UINT16) Ratio; ///< Replace Ratio
+ ///
+ /// Relative Power calculation per HSW BWG
+ ///
+ wPower1 = (mMaxBusRatio - FvidPointer[PssIndex].FvidState.BusRatio) * 625;
+ wPower1 = (110000 - wPower1);
+ wPower1 = DivU64x32 (wPower1, 11);
+ wPower1 = MultU64x64 (wPower1, wPower1);
+ //
+ // Power is calculated in milliwatts
+ //
+ wPower2 = (((FvidPointer[PssIndex].FvidState.BusRatio * 100) / mMaxBusRatio));
+ wPower2 = DivU64x32 (MultU64x32 (MultU64x64 (wPower2, wPower1), mPackageTdpWatt), 10000000);
+ FvidPointer[PssIndex].FvidState.Power = (UINT32) wPower2;
+}
+
+/**
+ Configures following fields of MSR 0x610 based on user configuration:
+ Configures Long duration Turbo Mode (power limit 1) power level and time window
+ Configures Short duration turbo mode (power limit 2)
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+**/
+VOID
+ConfigurePowerLimitsNonConfigTdpSkus (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ )
+{
+ MSR_REGISTER PakagePowerLimitMsr;
+ UINT16 ConvertedPowerLimit1;
+ UINT8 ConvertedPowerLimit1Time;
+ UINT16 ConvertedShortDurationPowerLimit;
+ UINT16 CpuConvertedPowerLimit1MaxLimit;
+ UINT16 CpuConvertedPowerLimit2MaxLimit;
+ UINT16 Multiplier;
+
+ CpuConvertedPowerLimit1MaxLimit = 0;
+ CpuConvertedPowerLimit2MaxLimit = 0;
+ ConvertedPowerLimit1Time = 0;
+ ///
+ /// By default, for Mobile & Desktop Processors: Short duration Power Limit = 1.25 * Package TDP
+ ///
+ Multiplier = 125;
+ ///
+ /// Check if TDP limits are programmable
+ /// - Platform Info MSR (0xCE) [29]
+ ///
+ if (mTdpLimitProgrammble) {
+ PakagePowerLimitMsr.Qword = AsmReadMsr64 (MSR_PACKAGE_POWER_LIMIT);
+ ///
+ /// Initialize the Power Limit 1 and Power Limit 1 enable bit
+ /// - Power Limit 1: Turbo Power Limit MSR [14:0]
+ /// - Power Limit 1 Enable: Turbo Power Limit MSR [15]
+ ///
+ ///
+ /// By default, program Power Limit 1 to Package TDP limit
+ ///
+ ConvertedPowerLimit1 = mPackageTdp;
+ if (CpuPmConfig->pTurboSettings->PowerLimit1 != AUTO) {
+ ///
+ /// CpuPmConfig->pTurboSettings->PowerLimit1 is in mW or watts. We need to convert it to
+ /// CPU Power unit, specified in PACKAGE_POWER_SKU_UNIT_MSR[3:0].
+ /// Since we are converting from Watts to CPU power units, multiply by
+ /// PACKAGE_POWER_SKU_UNIT_MSR[3:0].
+ /// Refer to BWG 14.13.7 for Power Limit 1 limits.
+ ///
+ ConvertedPowerLimit1 = (UINT16) ((CpuPmConfig->pTurboSettings->PowerLimit1 * mProcessorPowerUnit) / mCustomPowerUnit);
+ if (mPackageMaxPower == 0 && ConvertedPowerLimit1 >= mPackageMinPower) {
+ ///
+ /// If PACKAGE_POWER_SKU_MSR [46:32] = 0 means there is no upper limit ( since this field is 15 bits, the max value is 2^15 - 1 )
+ ///
+ CpuConvertedPowerLimit1MaxLimit = (UINT16) (LShiftU64 (2, 15) - 1);
+ if (ConvertedPowerLimit1 > CpuConvertedPowerLimit1MaxLimit) {
+ ///
+ /// If new Power Limit 1 is > CpuConvertedPowerLimit1MaxLimit, program Power Limit 1 to CpuConvertedPowerLimit1MaxLimit
+ ///
+ ConvertedPowerLimit1 = CpuConvertedPowerLimit1MaxLimit;
+ }
+ } else if (mPackageMinPower == 0 && ConvertedPowerLimit1 > 0 && ConvertedPowerLimit1 <= mPackageMaxPower) {
+ ///
+ /// If PACKAGE_POWER_SKU_MSR [30:16] = 0 means there is no lower limit
+ ///
+ ConvertedPowerLimit1 = (UINT16) ((CpuPmConfig->pTurboSettings->PowerLimit1 * mProcessorPowerUnit) / mCustomPowerUnit);
+
+ } else {
+ ///
+ /// Power Limit 1 needs to be between mPackageMinPower and mPackageMaxPower
+ ///
+ CpuConvertedPowerLimit1MaxLimit = mPackageMaxPower;
+
+ if (ConvertedPowerLimit1 < mPackageMinPower) {
+ ///
+ /// If new Power Limit 1 is < mPackageMinPower, program Power Limit 1 to mPackageMinPower
+ ///
+ ConvertedPowerLimit1 = mPackageMinPower;
+ } else if (ConvertedPowerLimit1 > CpuConvertedPowerLimit1MaxLimit) {
+ ///
+ /// If new Power Limit 1 is > mPackageMaxPower, program Power Limit 1 to mPackageMaxPower
+ ///
+ ConvertedPowerLimit1 = CpuConvertedPowerLimit1MaxLimit;
+ }
+ }
+ }
+ PakagePowerLimitMsr.Dwords.Low &= ~POWER_LIMIT_MASK;
+ PakagePowerLimitMsr.Dwords.Low |= (UINT32) (ConvertedPowerLimit1);
+ DEBUG (
+ (EFI_D_INFO,
+ "New Power Limit 1 %d watt (%d in CPU power unit)\n",
+ CpuPmConfig->pTurboSettings->PowerLimit1,
+ ConvertedPowerLimit1)
+ );
+ ///
+ /// Force Power Limit 1 override to be enabled
+ ///
+ PakagePowerLimitMsr.Dwords.Low |= B_POWER_LIMIT_ENABLE;
+ ///
+ /// Program Power Limit 1 (Long Duration Turbo) Time Window
+ /// If PowerLimit1Time is AUTO OR If PowerLimit1Time is > MAX_POWER_LIMIT_1_TIME_IN_SECONDS
+ /// program default values
+ ///
+ if ((CpuPmConfig->pTurboSettings->PowerLimit1Time == AUTO) ||
+ (CpuPmConfig->pTurboSettings->PowerLimit1Time > MAX_POWER_LIMIT_1_TIME_IN_SECONDS)
+ ) {
+ if (IS_SA_DEVICE_ID_MOBILE(mProcessorFlavor)) {
+ ///
+ /// For Mobile, default value is 28 seconds
+ ///
+ CpuPmConfig->pTurboSettings->PowerLimit1Time = MB_POWER_LIMIT1_TIME_DEFAULT;
+ } else {
+ ///
+ /// For Desktop, default value is 1 second
+ ///
+ CpuPmConfig->pTurboSettings->PowerLimit1Time = DT_POWER_LIMIT1_TIME_DEFAULT;
+ }
+ }
+ ConvertedPowerLimit1Time = GetConvertedTime (CpuPmConfig->pTurboSettings->PowerLimit1Time, PL12TimeWindowCovert);
+ ///
+ /// Configure Power Limit 1 (Long Duration Turbo) time windows: Turbo Power Limit MSR [23:17]
+ ///
+ PakagePowerLimitMsr.Dwords.Low &= ~POWER_LIMIT_1_TIME_MASK;
+ PakagePowerLimitMsr.Dwords.Low |= (UINT32) LShiftU64 (ConvertedPowerLimit1Time, 17);
+ ///
+ /// Initialize Short Duration Power limit and enable bit
+ /// Short duration Power Limit: Turbo Power Limit MSR (0x450h) [46:32]
+ /// Short duration Power Limit Enable:Turbo Power Limit MSR (0x450h) [47]
+ ///
+ /// CpuPmConfig->pTurboSettings->PowerLimit2 value is in mW or watts. We need to convert it to
+ /// CPU Power unit, specified in PACKAGE_POWER_SKU_UNIT_MSR[3:0].
+ /// Since we are converting from Watts to CPU power units, multiply by
+ /// PACKAGE_POWER_SKU_UNIT_MSR[3:0]
+ ///
+ ConvertedShortDurationPowerLimit = (UINT16) ((CpuPmConfig->pTurboSettings->PowerLimit2 * mProcessorPowerUnit) / mCustomPowerUnit);
+ PakagePowerLimitMsr.Dwords.High &= ~(POWER_LIMIT_MASK | B_POWER_LIMIT_ENABLE);
+ ///
+ /// If PowerLimit2 is AUTO OR if PowerLimit2 is > mPackageMaxPower OR if PowerLimit2 < mPackageMinPower
+ /// program defaul values.
+ ///
+ CpuConvertedPowerLimit2MaxLimit = mPackageMaxPower;
+ if (CpuConvertedPowerLimit2MaxLimit == 0) {
+ CpuConvertedPowerLimit2MaxLimit = (UINT16) (LShiftU64 (2, 15) - 1);
+ }
+ if (CpuPmConfig->pTurboSettings->PowerLimit2 == AUTO) {
+ ConvertedShortDurationPowerLimit = EFI_IDIV_ROUND ((Multiplier * mPackageTdp), 100);
+
+ }
+ if (ConvertedShortDurationPowerLimit > CpuConvertedPowerLimit2MaxLimit) {
+ ConvertedShortDurationPowerLimit = CpuConvertedPowerLimit2MaxLimit;
+ }
+ if (ConvertedShortDurationPowerLimit < mPackageMinPower) {
+ ConvertedShortDurationPowerLimit = mPackageMinPower;
+ }
+ PakagePowerLimitMsr.Dwords.High |= (UINT32) (ConvertedShortDurationPowerLimit);
+
+ if (CpuPmConfig->pFunctionEnables->PowerLimit2 == PPM_ENABLE) {
+ PakagePowerLimitMsr.Dwords.High |= B_POWER_LIMIT_ENABLE;
+ } else {
+ PakagePowerLimitMsr.Dwords.High &= (~B_POWER_LIMIT_ENABLE);
+ }
+
+ DEBUG (
+ (EFI_D_INFO,
+ "Short duration Power limit enabled, Power Limit = %d Watts\n",
+ CpuPmConfig->pTurboSettings->PowerLimit2)
+ );
+
+ DEBUG ((EFI_D_INFO,"MSR(610h)=%08X%08X\n",PakagePowerLimitMsr.Dwords.High,PakagePowerLimitMsr.Dwords.Low));
+
+ AsmWriteMsr64 (MSR_PACKAGE_POWER_LIMIT, PakagePowerLimitMsr.Qword);
+ }
+
+ ///
+ /// Enable Power Clamp when Controllable TDP is enabled.
+ ///
+ if (mControllableTdpEnable) {
+ PakagePowerLimitMsr.Qword = AsmReadMsr64 (MSR_PACKAGE_POWER_LIMIT);
+ PakagePowerLimitMsr.Dwords.Low |= B_CRITICAL_POWER_CLAMP_ENABLE;
+ DEBUG ((EFI_D_INFO, "Critical Power Clamp1 enabled : %x\n",PakagePowerLimitMsr.Qword));
+ AsmWriteMsr64 (MSR_PACKAGE_POWER_LIMIT, PakagePowerLimitMsr.Qword);
+ }
+
+ ///
+ ///BIOS to override 41W PL1 for 47W 2C parts (Cahce Size = 3MB)
+ ///
+ if((CpuPmConfig->pTurboSettings->PowerLimit1 == AUTO) && (mPackageTdp == 47) && (mCpuCacheSize == 3 * 1024)) {
+ PakagePowerLimitMsr.Qword = AsmReadMsr64 (MSR_PACKAGE_POWER_LIMIT);
+ PakagePowerLimitMsr.Dwords.Low &= ~POWER_LIMIT_MASK;
+ PakagePowerLimitMsr.Dwords.Low |= (UINT32) ((41 * mProcessorPowerUnit) & POWER_LIMIT_MASK);
+ AsmWriteMsr64 (MSR_PACKAGE_POWER_LIMIT, PakagePowerLimitMsr.Qword);
+ }
+ ///
+ /// PL1 and PL2 BIOS Overrides for 57W Non CTDP SKU
+ ///
+ if((CpuPmConfig->pTurboSettings->PowerLimit1 == AUTO) &&
+ (CpuPmConfig->pTurboSettings->PowerLimit2 == AUTO) &&
+ (mPackageTdp == 57 * mProcessorPowerUnit)) {
+ PakagePowerLimitMsr.Qword = AsmReadMsr64 (MSR_PACKAGE_POWER_LIMIT);
+ ///
+ /// PL1=67W
+ ///
+ PakagePowerLimitMsr.Dwords.Low &= ~POWER_LIMIT_MASK;
+ PakagePowerLimitMsr.Dwords.Low |= (UINT32) ((67 * mProcessorPowerUnit) & POWER_LIMIT_MASK);
+ ///
+ /// PL2=83.75W
+ ///
+ PakagePowerLimitMsr.Dwords.High &= ~POWER_LIMIT_MASK;
+ PakagePowerLimitMsr.Dwords.High |= (UINT32) (((8375 * mProcessorPowerUnit) / 100) & POWER_LIMIT_MASK);
+
+ AsmWriteMsr64 (MSR_PACKAGE_POWER_LIMIT, PakagePowerLimitMsr.Qword);
+ }
+ //
+ // End if ((PlatformInfoMsr.Dwords.Low & B_EFI_PLATFORM_INFO_TDC_TDP_LIMIT))
+ //
+ ///
+ /// Pass the power limits of the non-CTDP part to the Global NVS Area for use by DPTF
+ ///
+ PakagePowerLimitMsr.Qword = AsmReadMsr64 (MSR_PACKAGE_POWER_LIMIT);
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[0].CtdpPowerLimit1 = (UINT16) (PakagePowerLimitMsr.Dwords.Low & POWER_LIMIT_MASK);
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[0].CtdpPowerLimit2 = (UINT16) (PakagePowerLimitMsr.Dwords.High & POWER_LIMIT_MASK);
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[0].CtdpPowerLimitWindow = (UINT8) CpuPmConfig->pTurboSettings->PowerLimit1Time;
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[0].CtdpTar = (UINT8) mTurboBusRatio;
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[0].CtdpCtc = 1;
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelsSupported = 1;
+ mPpmGlobalNvsAreaProtocol->Area->ConfigTdpBootModeIndex = 0;
+}
+
+/**
+ Configures following fields of MSR 0x615
+ Configures power limit 3 power level and time window
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+**/
+VOID
+ConfigurePL3PowerLimits (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ )
+{
+ MSR_REGISTER PlatformPowerLimitMsr;
+ UINT16 ConvertedPowerLimit3;
+ UINT8 ConvertedPowerLimit3Time;
+ CPU_STEPPING CpuSteppingId;
+ CPU_FAMILY CpuFamilyId;
+
+ CpuFamilyId = mPpmGlobalNvsAreaProtocol->Area->Cpuid & CPUID_FULL_FAMILY_MODEL;
+ CpuSteppingId = mPpmGlobalNvsAreaProtocol->Area->Cpuid & CPUID_FULL_STEPPING;
+
+ ///
+ /// PL3 is supported on HSW ULT C0 & HSW C0 and later
+ ///
+ if(((CpuFamilyId == EnumCpuHsw) && (CpuSteppingId >= EnumHswC0))
+ || ((CpuFamilyId == EnumCpuHswUlt) && (CpuSteppingId >= EnumHswUltC0))) {
+ ///
+ /// Return if No user overrides selected.
+ ///
+ if((CpuPmConfig->pTurboSettings->PowerLimit3 == AUTO)
+ && (CpuPmConfig->pTurboSettings->PowerLimit3Time == AUTO)
+ && (CpuPmConfig->pTurboSettings->PowerLimit3DutyCycle == AUTO)){
+ return;
+ }
+
+ PlatformPowerLimitMsr.Qword = AsmReadMsr64 (MSR_PLATFORM_POWER_LIMIT);
+ DEBUG ((EFI_D_INFO," PL3 MSR 615 Before Writing %x ",PlatformPowerLimitMsr.Dwords.Low));
+ ///
+ /// Configure PL3 Power Limit if custom value is avaiable
+ ///
+ if (CpuPmConfig->pTurboSettings->PowerLimit3 != AUTO) {
+ ConvertedPowerLimit3 = (UINT16) ((CpuPmConfig->pTurboSettings->PowerLimit3 * mProcessorPowerUnit) / mCustomPowerUnit);
+ PlatformPowerLimitMsr.Dwords.Low &= ~POWER_LIMIT_MASK;
+ PlatformPowerLimitMsr.Dwords.Low |= (UINT32) (ConvertedPowerLimit3);
+ PlatformPowerLimitMsr.Dwords.Low |= B_POWER_LIMIT_ENABLE;
+ }
+
+ ///
+ /// Configure PL3 Time window if custom value is avaiable
+ ///
+ if (CpuPmConfig->pTurboSettings->PowerLimit3Time != AUTO) {
+ ConvertedPowerLimit3Time = GetConvertedTime (CpuPmConfig->pTurboSettings->PowerLimit3Time, PL3TimeWindowConvert);
+ PlatformPowerLimitMsr.Dwords.Low &= ~POWER_LIMIT_3_TIME_MASK;
+ PlatformPowerLimitMsr.Dwords.Low |= (UINT32) LShiftU64 (ConvertedPowerLimit3Time, 17);
+ PlatformPowerLimitMsr.Dwords.Low |= B_POWER_LIMIT_ENABLE;
+ }
+
+ ///
+ /// Configure PL3 Duty Cycle if custom value is avaiable
+ ///
+ if (CpuPmConfig->pTurboSettings->PowerLimit3DutyCycle != AUTO) {
+ PlatformPowerLimitMsr.Dwords.Low &= ~POWER_LIMIT_3_DUTY_CYCLE_MASK;
+ PlatformPowerLimitMsr.Dwords.Low |= (UINT32) LShiftU64 (CpuPmConfig->pTurboSettings->PowerLimit3DutyCycle, 24);
+ PlatformPowerLimitMsr.Dwords.Low |= B_POWER_LIMIT_ENABLE;
+ }
+ //
+ // Enable/Disable PL3 lock
+ //
+ if (CpuPmConfig->pTurboSettings->PowerLimit3Lock == PPM_ENABLE) {
+ PlatformPowerLimitMsr.Dwords.Low |= (UINT32) B_POWER_LIMIT_LOCK;
+ }else {
+ PlatformPowerLimitMsr.Dwords.Low &= (~((UINT32) B_POWER_LIMIT_LOCK));
+ }
+
+ AsmWriteMsr64 (MSR_PLATFORM_POWER_LIMIT, PlatformPowerLimitMsr.Qword);
+ DEBUG ((EFI_D_INFO," PL3 MSR 615 After Writing %x ",PlatformPowerLimitMsr.Dwords.Low));
+ } // End if Processor Check
+}
+
+/**
+ Configures following fields of MSR 0x610
+ Configures Long duration Turbo Mode (power limit 1) power level and time window
+ Configures Short duration turbo mode (power limit 2)
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+**/
+VOID
+ConfigureCtdpPowerLimits (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ )
+{
+ MSR_REGISTER PakagePowerLimitMsr;
+ UINT16 ConvertedPowerLimit1;
+ UINT16 ConvertedPowerLimit2;
+ UINT8 ConvertedPowerLimit1Time;
+ UINT16 Mutliplier;
+ UINTN Index;
+ CPU_FAMILY mCpuFamilyId;
+
+ mCpuFamilyId = mPpmGlobalNvsAreaProtocol->Area->Cpuid & CPUID_FULL_FAMILY_MODEL;
+ ConvertedPowerLimit1Time = 0;
+ ///
+ /// By default, for Mobile & Desktop Processors: Short duration Power Limit = 1.25 * Package TDP
+ ///
+ Mutliplier = 125;
+ //
+ // For ConfigTdp enabled skus
+ //
+ PakagePowerLimitMsr.Qword = AsmReadMsr64 (MSR_PACKAGE_POWER_LIMIT);
+ PakagePowerLimitMsr.Dwords.Low &= ~POWER_LIMIT_MASK;
+ PakagePowerLimitMsr.Dwords.High &= ~POWER_LIMIT_MASK;
+ ///
+ /// Initialize the Power Limit 1/2 and Power Limit 2 enable bit in MSR
+ /// Power Limit 1: Turbo Power Limit MSR [14:0] and Power Limit 2: Turbo Power Limit MSR [46:32]
+ /// Set MSR value for Power Limit 1/2 to Max Package Power Value or Maximum Supported Value
+ ///
+ ///
+ if (mPackageMaxPower) {
+ ConvertedPowerLimit1 = mPackageMaxPower;
+ ///
+ /// Short duration Power Limit (PL2) = 1.25 * PL1
+ ///
+ ConvertedPowerLimit2 = EFI_IDIV_ROUND ((Mutliplier * ConvertedPowerLimit1), 100);
+ if (ConvertedPowerLimit2 > PACKAGE_TDP_POWER_MASK) {
+ ConvertedPowerLimit2 = PACKAGE_TDP_POWER_MASK;
+ }
+ } else {
+ ///
+ /// Set Maximum value for Turbo Power Limit MSR [14:0] and [46:32] =
+ /// Max of CTDP Level Power Limts
+ ///
+ ConvertedPowerLimit1 = 0;
+ for (Index = 0; Index < mPpmGlobalNvsAreaProtocol->Area->CtdpLevelsSupported; Index++) {
+ if (ConvertedPowerLimit1 < mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[Index].CtdpPowerLimit1) {
+ ConvertedPowerLimit1 = mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[Index].CtdpPowerLimit1;
+ }
+ }
+ ConvertedPowerLimit2 = 0;
+ for (Index = 0; Index < mPpmGlobalNvsAreaProtocol->Area->CtdpLevelsSupported; Index++) {
+ if (ConvertedPowerLimit2 < mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[Index].CtdpPowerLimit2) {
+ ConvertedPowerLimit2 = mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[Index].CtdpPowerLimit2;
+ }
+ }
+ }
+ ///
+ /// Program Power Limit 1 (Long Duration Turbo) Time Window
+ /// If PowerLimit1Time is AUTO OR If PowerLimit1Time is > MAX_POWER_LIMIT_1_TIME_IN_SECONDS
+ /// program default values
+ ///
+ if (CpuPmConfig->pCustomCtdpSettings->ConfigTdpCustom == PPM_ENABLE) {
+ ConvertedPowerLimit1Time = GetConvertedTime (CpuPmConfig->pCustomCtdpSettings->CustomConfigTdpTable[0].CustomPowerLimit1Time, PL12TimeWindowCovert);
+ } else {
+ if (IS_SA_DEVICE_ID_MOBILE(mProcessorFlavor)) {
+ ///
+ /// For Mobile, default value is 28 seconds
+ ///
+ CpuPmConfig->pTurboSettings->PowerLimit1Time = MB_POWER_LIMIT1_TIME_DEFAULT;
+ } else {
+ ///
+ /// For Desktop, default value is 1 second
+ ///
+ CpuPmConfig->pTurboSettings->PowerLimit1Time = DT_POWER_LIMIT1_TIME_DEFAULT;
+ }
+ ConvertedPowerLimit1Time = GetConvertedTime (CpuPmConfig->pTurboSettings->PowerLimit1Time, PL12TimeWindowCovert);
+ }
+ ///
+ /// Configure Power Limit 1 (Long Duration Turbo) time windows: Turbo Power Limit MSR [23:17]
+ ///
+ PakagePowerLimitMsr.Dwords.Low &= ~POWER_LIMIT_1_TIME_MASK;
+ PakagePowerLimitMsr.Dwords.Low |= (UINT32) LShiftU64 (ConvertedPowerLimit1Time, 17);
+ PakagePowerLimitMsr.Dwords.High |= B_POWER_LIMIT_ENABLE;
+ PakagePowerLimitMsr.Dwords.Low |= (UINT32) (ConvertedPowerLimit1);
+ PakagePowerLimitMsr.Dwords.High |= (UINT32) (ConvertedPowerLimit2);
+ AsmWriteMsr64 (MSR_PACKAGE_POWER_LIMIT, PakagePowerLimitMsr.Qword);
+}
+
+/**
+ Configures BIOS overrides in MSR 0x610
+ Configures Long duration Turbo Mode (power limit 1) power level and time window
+ Configures Short duration turbo mode (power limit 2)
+
+ @param[in] None
+**/
+VOID
+ConfigureCtdpPowerLimitsOverrides (
+ ){
+ UINTN Index;
+ UINTN NoOfOverrides;
+ CPU_FAMILY mCpuFamilyId;
+ UINT32 LibStatus;
+ UINT32 IccMaxValue;
+ EFI_STATUS Status;
+ UINTN PackageTdp;
+ MSR_REGISTER PakagePowerLimitMsr;
+ PPM_CTDP_OVERRIDE_TABLE *PpmCtdpOverideTable;
+
+ mCpuFamilyId = mPpmGlobalNvsAreaProtocol->Area->Cpuid & CPUID_FULL_FAMILY_MODEL;
+
+ if(mCpuFamilyId == EnumCpuHswUlt) {
+ PpmCtdpOverideTable = mHswUltPpmCtdpOverideTable;
+ NoOfOverrides = (sizeof(mHswUltPpmCtdpOverideTable))/(sizeof(PPM_CTDP_OVERRIDE_TABLE));
+ }else {
+ return;
+ }
+
+ PackageTdp = (mPackageTdpWatt * 100);
+ if((mPackageTdp % mProcessorPowerUnit) !=0) {
+ PackageTdp += ((mPackageTdp % mProcessorPowerUnit)* 100) / mProcessorPowerUnit ;
+ }
+
+ for(Index = 0; Index < NoOfOverrides;Index++,PpmCtdpOverideTable++) {
+ if(PpmCtdpOverideTable->SkuPackageTdp == PackageTdp) {
+
+ if(PpmCtdpOverideTable->SkuIccMax) {
+ ///
+ /// If SkuIccMax is not Zero check ICC Max for SKU detection.if No match go to next entry.
+ /// Read Icc Max from BIOS P code Mail box
+ ///
+ Status = MailboxRead(MAILBOX_TYPE_PCODE, READ_ICC_MAX_CMD, &IccMaxValue, &LibStatus);
+ IccMaxValue = IccMaxValue & 0x0FFF;
+ IccMaxValue = IccMaxValue /8;
+ if ((Status == EFI_SUCCESS) && (IccMaxValue != 0) && (IccMaxValue != PpmCtdpOverideTable->SkuIccMax)) {
+ continue;
+ }
+ }
+
+ DEBUG ((EFI_D_INFO, "PPM:: Ctdp BIOS PL1/PL2 Override Ctdp SKU Found :%d override table index :%d\n",PpmCtdpOverideTable->SkuPackageTdp,Index));
+ ///
+ /// MSR Overrides
+ ///
+ PakagePowerLimitMsr.Qword = AsmReadMsr64 (MSR_PACKAGE_POWER_LIMIT);
+ if(PpmCtdpOverideTable->MsrCtdpPowerLimit1) {
+ PakagePowerLimitMsr.Dwords.Low &= ~POWER_LIMIT_MASK;
+ PakagePowerLimitMsr.Dwords.Low |= ((PpmCtdpOverideTable->MsrCtdpPowerLimit1 * mProcessorPowerUnit)/100) & POWER_LIMIT_MASK;
+ }
+ if(PpmCtdpOverideTable->MsrCtdpPowerLimit2) {
+ PakagePowerLimitMsr.Dwords.High &= ~POWER_LIMIT_MASK;
+ PakagePowerLimitMsr.Dwords.High |=((PpmCtdpOverideTable->MsrCtdpPowerLimit2 * mProcessorPowerUnit)/100) & POWER_LIMIT_MASK;
+ }
+ AsmWriteMsr64 (MSR_PACKAGE_POWER_LIMIT, PakagePowerLimitMsr.Qword);
+
+ ///
+ /// MMIO Overrides
+ ///
+ if(PpmCtdpOverideTable->CtdpNominalPowerLimit1) {
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[0].CtdpPowerLimit1 = (UINT16)(PpmCtdpOverideTable->CtdpNominalPowerLimit1 * mProcessorPowerUnit)/100;
+ }
+ if(PpmCtdpOverideTable->CtdpNominalPowerLimit2) {
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[0].CtdpPowerLimit2 = (UINT16)(PpmCtdpOverideTable->CtdpNominalPowerLimit2 * mProcessorPowerUnit)/100;
+ }
+ if(PpmCtdpOverideTable->CtdpDownPowerLimit1) {
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[1].CtdpPowerLimit1 = (UINT16)(PpmCtdpOverideTable->CtdpDownPowerLimit1 * mProcessorPowerUnit)/100;
+ }
+ if(PpmCtdpOverideTable->CtdpDownPowerLimit2) {
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[1].CtdpPowerLimit2 = (UINT16)(PpmCtdpOverideTable->CtdpDownPowerLimit2 * mProcessorPowerUnit)/100;
+ }
+ if(PpmCtdpOverideTable->CtdpDownPowerLimit1) {
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[2].CtdpPowerLimit1 = (UINT16)(PpmCtdpOverideTable->CtdpUpPowerLimit1 * mProcessorPowerUnit)/100;
+ }
+ if(PpmCtdpOverideTable->CtdpUpPowerLimit2) {
+ mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[2].CtdpPowerLimit2 = (UINT16)(PpmCtdpOverideTable->CtdpUpPowerLimit2 * mProcessorPowerUnit)/100;
+ }
+ break;
+ }
+ }
+}
+
+/**
+ Configure cTDP BIOS MSRs to Boot Ctdp values
+ - Configures CONFIG_TDP_CONTROL MSR
+ - Configures TURBO_ACTIVATION_RATIO MSR
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+ @param[in] CpuConfigTdpBootLevel ConfigTdpBootLevel policy setting by user
+**/
+VOID
+SelectCtdpLevel (
+ IN POWER_MGMT_CONFIG *CpuPmConfig,
+ IN UINT8 CpuConfigTdpBootLevel
+ )
+{
+ MSR_REGISTER TempMsr;
+
+ ///
+ /// Select cTDP Nominal if Ctdp disabled or boot level not supported.
+ ///
+ if (CpuConfigTdpBootLevel == CONFIG_TDP_DEACTIVATE || CpuConfigTdpBootLevel >= mPpmGlobalNvsAreaProtocol->Area->CtdpLevelsSupported) {
+ CpuConfigTdpBootLevel = 0;
+ }
+
+ mCpuConfigTdpBootRatio = mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[CpuConfigTdpBootLevel].CtdpTar+1;
+ mPpmGlobalNvsAreaProtocol->Area->ConfigurablePpc = mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[CpuConfigTdpBootLevel].CtdpPpc;
+ ///
+ /// Program the selected level 00:nominal,01:level1,10:level2 to
+ /// CONFIG TDP CONTROL MSR.
+ ///
+ TempMsr.Qword = AsmReadMsr64 (MSR_CONFIG_TDP_CONTROL);
+ if ((TempMsr.Qword & CONFIG_TDP_CONTROL_LOCK) == 0) {
+ TempMsr.Dwords.Low = (UINT16) TempMsr.Dwords.Low &~CONFIG_TDP_CONTROL_LVL_MASK;
+ TempMsr.Dwords.Low = (UINT16) TempMsr.Dwords.Low | (CpuConfigTdpBootLevel & CONFIG_TDP_CONTROL_LVL_MASK);
+ if (CpuPmConfig->pTurboSettings->ConfigTdpLock == PPM_ENABLE) {
+ TempMsr.Dwords.Low |= CONFIG_TDP_CONTROL_LOCK;
+ DEBUG ((EFI_D_INFO, "PPM:: ConfigTDP MSR_CONFIG_TDP_CONTROL is locked\n"));
+ }
+ AsmWriteMsr64 (MSR_CONFIG_TDP_CONTROL, TempMsr.Qword);
+ DEBUG ((EFI_D_INFO, "PPM:: ConfigTDP MSR_CONFIG_TDP_CONTROL=%x\n", TempMsr.Qword));
+ } else {
+ DEBUG ((EFI_D_INFO, "PPM:: Could not write MSR_CONFIG_TDP_CONTROL\n"));
+ }
+ ///
+ /// Program the max non-turbo ratio corresponding to default selected level
+ /// in TURBO_ACTIVATION_RATIO MSR.
+ ///
+ TempMsr.Qword = AsmReadMsr64 (MSR_TURBO_ACTIVATION_RATIO);
+ if ((TempMsr.Qword & MSR_TURBO_ACTIVATION_RATIO_LOCK) == 0) {
+ TempMsr.Dwords.Low &= ~MSR_TURBO_ACTIVATION_RATIO_MASK;
+ TempMsr.Dwords.Low |= (UINT16) ((mCpuConfigTdpBootRatio-1) & MSR_TURBO_ACTIVATION_RATIO_MASK);
+ if (CpuPmConfig->pTurboSettings->ConfigTdpLock == PPM_ENABLE ) {
+ TempMsr.Dwords.Low |= MSR_TURBO_ACTIVATION_RATIO_LOCK;
+ DEBUG ((EFI_D_INFO, "PPM:: ConfigTDP MSR_TURBO_ACTIVATION_RATIO is locked\n"));
+ }
+ AsmWriteMsr64 (MSR_TURBO_ACTIVATION_RATIO, TempMsr.Qword);
+ DEBUG ((EFI_D_INFO, "PPM:: ConfigTDP MSR_TURBO_ACTIVATION_RATIO=%x\n", TempMsr.Qword));
+ } else {
+ DEBUG ((EFI_D_INFO, "PPM:: Could not write MSR_TURBO_ACTIVATION_RATIO\n"));
+ }
+}
+
+/**
+ Configures the TURBO_POWER_LIMIT MMIO for Boot ConfigTdp Level
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+ @param[in] CpuConfigTdpBootLevel ConfigTdpBootLevel policy setting by user
+**/
+VOID
+SelectCtdpPowerLimits (
+ IN POWER_MGMT_CONFIG *CpuPmConfig,
+ IN UINT8 CpuConfigTdpBootLevel
+ )
+{
+ UINTN PciD0F0RegBase;
+ UINTN MchBar;
+ UINT32 Data32And;
+ UINT32 Data32Or;
+ UINT16 PowerLimit1;
+ UINT16 PowerLimit2;
+ MSR_REGISTER TempMsr;
+
+ ///
+ /// If Ctdp deactivate, Program MSRs to Nominal and MMIO to 0 to enable overclocking
+ ///
+ if (CpuConfigTdpBootLevel == CONFIG_TDP_DEACTIVATE) {
+ PowerLimit1 = mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[0].CtdpPowerLimit1;
+ PowerLimit2 = mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[0].CtdpPowerLimit2;
+ TempMsr.Qword = AsmReadMsr64 (MSR_PACKAGE_POWER_LIMIT);
+ TempMsr.Dwords.Low &= ~POWER_LIMIT_MASK;
+ TempMsr.Dwords.Low |= PowerLimit1;
+ TempMsr.Dwords.High &= ~POWER_LIMIT_MASK;
+ TempMsr.Dwords.High |= PowerLimit2;
+ AsmWriteMsr64 (MSR_PACKAGE_POWER_LIMIT, TempMsr.Qword);
+ return;
+ }
+
+ ///
+ /// Select cTDP Nominal if Ctdp disabled or boot level not supported.
+ ///
+ if (CpuConfigTdpBootLevel >= mPpmGlobalNvsAreaProtocol->Area->CtdpLevelsSupported) {
+ CpuConfigTdpBootLevel = 0;
+ }
+
+ PowerLimit1 = mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[CpuConfigTdpBootLevel].CtdpPowerLimit1;
+ PowerLimit2 = mPpmGlobalNvsAreaProtocol->Area->CtdpLevelSettings[CpuConfigTdpBootLevel].CtdpPowerLimit2;
+ ///
+ /// Get the MCH space base address.
+ /// Program Turbo Power Limit MMIO register MCHBAR+0x59A0 Bits [14:0] and [46:32]
+ /// for ConfigTdp mode PL1 and PL2
+ ///
+ PciD0F0RegBase = MmPciAddress (0, 0, 0, 0, 0);
+ MchBar = MmioRead32 (PciD0F0RegBase + 0x48) &~BIT0;
+ ///
+ /// Read PowerLimit MSR
+ ///
+ TempMsr.Qword = AsmReadMsr64 (MSR_PACKAGE_POWER_LIMIT);
+ ///
+ /// Program cTDP Power Limit1
+ ///
+ Data32And = (UINT32) ~(PACKAGE_TDP_POWER_MASK);
+ Data32Or = (UINT32) (PowerLimit1 | (TempMsr.Dwords.Low &~PACKAGE_TDP_POWER_MASK));
+ MmioAndThenOr32 (MchBar + MMIO_TURBO_POWER_LIMIT, Data32And, Data32Or);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (MchBar + MMIO_TURBO_POWER_LIMIT),
+ 1,
+ (VOID *) (UINTN) (MchBar + MMIO_TURBO_POWER_LIMIT)
+ );
+ ///
+ /// Program cTDP Power Limit2
+ ///
+ Data32And = (UINT32) ~(PACKAGE_TDP_POWER_MASK);
+ Data32Or = (UINT32) (PowerLimit2 | (TempMsr.Dwords.High &~PACKAGE_TDP_POWER_MASK));
+ MmioAndThenOr32 (MchBar + MMIO_TURBO_POWER_LIMIT + 4, Data32And, Data32Or);
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (MchBar + MMIO_TURBO_POWER_LIMIT + 4),
+ 1,
+ (VOID *) (UINTN) (MchBar + MMIO_TURBO_POWER_LIMIT + 4)
+ );
+}
+
+
+/**
+ Configures following fields of MSR 0x618 based on corresponding MMIO register (MCHBAR+0x58E0):
+ Configures Long duration Turbo Mode (power limit 1) power level and time window for DDR domain
+ Configures Short duration Turbo Mode (power limit 2) power level and time window for DDR domain
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+**/
+VOID
+ConfigureDdrPowerLimits (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ )
+{
+ MSR_REGISTER DdrPowerLimitMsr;
+ UINTN PciD0F0RegBase;
+ UINTN MchBar;
+
+ PciD0F0RegBase = MmPciAddress (0, 0, 0, 0, 0);
+ MchBar = MmioRead32 (PciD0F0RegBase + 0x48) &~BIT0;
+
+ DdrPowerLimitMsr.Qword = 0;
+ DdrPowerLimitMsr.Qword = MmioRead64 (MchBar + MMIO_DDR_RAPL_LIMIT);
+
+ DEBUG (
+ (EFI_D_INFO,
+ "DDR Power Limit 1 = %d\n",
+ DdrPowerLimitMsr.Dwords.Low & POWER_LIMIT_MASK)
+ );
+ DEBUG (
+ (EFI_D_INFO,
+ "DDR Power Limit 2 = %d\n",
+ DdrPowerLimitMsr.Dwords.High & POWER_LIMIT_MASK)
+ );
+
+ AsmWriteMsr64 (MSR_DDR_RAPL_LIMIT, DdrPowerLimitMsr.Qword);
+}
+
+/**
+ Configures PowerLimits and Config TDP values
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+**/
+VOID
+ConfigureCtdp (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ )
+{
+ ///
+ /// Configure CTDP power limits.Refer Rev 0.6.0 BWG sec 16.7.1: Enabling Intel Configurable TDP support
+ ///
+ ConfigureCtdpPowerLimits (CpuPmConfig);
+
+ ///
+ /// BIOS power limit overrides
+ /// Don't override if custom ctdp settings are provided.
+ ///
+ if (!CpuPmConfig->pCustomCtdpSettings->ConfigTdpCustom) {
+ ConfigureCtdpPowerLimitsOverrides();
+ }
+ ///
+ /// To avoid issues and race conditions it is recommended that the below order of be followed
+ /// - For TDP Up program the Config TDP Level followed by Power Limits
+ /// - For TDP down program the Power Limits followed by Config TDP level
+ ///
+ if (CpuPmConfig->pTurboSettings->ConfigTdpLevel == CONFIG_TDP_UP) {
+ SelectCtdpPowerLimits (CpuPmConfig, mPpmGlobalNvsAreaProtocol->Area->ConfigTdpBootModeIndex);
+ SelectCtdpLevel (CpuPmConfig, mPpmGlobalNvsAreaProtocol->Area->ConfigTdpBootModeIndex);
+ } else {
+ SelectCtdpLevel (CpuPmConfig, mPpmGlobalNvsAreaProtocol->Area->ConfigTdpBootModeIndex);
+ SelectCtdpPowerLimits (CpuPmConfig, mPpmGlobalNvsAreaProtocol->Area->ConfigTdpBootModeIndex);
+ }
+}
+
+EFI_STATUS
+InitControllableTdp (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ )
+/**
+ Check for Ctrl TDP enabled SKUs and enable Controllable TDP
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+
+ @exception EFI_UNSUPPORTED Controllable TDP not Supported
+ @retval EFI_SUCCESS Controllable TDP Supported
+**/
+{
+ UINTN CpuFamilyIndex;
+ UINTN CpuModelIndex;
+ UINT32 CtrlTdpSkuSize;
+ UINT8 CtrlTdpSkuDetected;
+ CHAR8 BrandIdString[MAXIMUM_CPU_BRAND_STRING_LENGTH + 1];
+ CPU_FAMILY CpuFamilyId;
+ CPU_STEPPING CpuSteppingId;
+ EFI_CPUID_REGISTER CpuExtendedSupport;
+ EFI_CPUID_REGISTER CpuBrandString;
+ PPM_CTRL_TDP_SKU_TBL *CtrlTdpSku;
+ MSR_REGISTER TempMsr;
+///
+/// Debug
+///
+
+ CtrlTdpSkuDetected = 0;
+ CtrlTdpSkuSize = 0;
+
+ CpuFamilyId = mPpmGlobalNvsAreaProtocol->Area->Cpuid & CPUID_FULL_FAMILY_MODEL;
+ CpuSteppingId = mPpmGlobalNvsAreaProtocol->Area->Cpuid & CPUID_FULL_STEPPING;
+
+ if((CpuFamilyId == EnumCpuHswUlt) || (CpuFamilyId == EnumCpuHsw) || (CpuFamilyId == EnumCpuCrw)) {
+ CtrlTdpSku = mHswCtrlTdpSkuTable;
+ CtrlTdpSkuSize = 1;
+ }else {
+ return EFI_UNSUPPORTED;
+ }
+
+ DEBUG ((EFI_D_ERROR, "\n Function InitControllableTdp \n"));
+ //
+ // Get CPU Brand String
+ //
+ AsmCpuid (CPUID_EXTENDED_FUNCTION, &CpuExtendedSupport.RegEax, &CpuExtendedSupport.RegEbx, &CpuExtendedSupport.RegEcx, &CpuExtendedSupport.RegEdx);
+ AsmCpuid (CPUID_BRAND_STRING1, &CpuBrandString.RegEax, &CpuBrandString.RegEbx, &CpuBrandString.RegEcx, &CpuBrandString.RegEdx);
+ //
+ // Check if Brand ID String is supported or filled up
+ //
+ if (CpuExtendedSupport.RegEax == 0) {
+ return EFI_UNSUPPORTED;
+ }
+ CopyMem ((CHAR8 *) &BrandIdString[0],(CHAR8 *) &CpuBrandString,16);
+ AsmCpuid (CPUID_BRAND_STRING2, &CpuBrandString.RegEax, &CpuBrandString.RegEbx, &CpuBrandString.RegEcx, &CpuBrandString.RegEdx);
+ CopyMem ((CHAR8 *) &BrandIdString[16],(CHAR8 *) &CpuBrandString,16);
+ AsmCpuid (CPUID_BRAND_STRING3, &CpuBrandString.RegEax, &CpuBrandString.RegEbx, &CpuBrandString.RegEcx, &CpuBrandString.RegEdx);
+ CopyMem ((CHAR8 *) &BrandIdString[31],(CHAR8 *) &CpuBrandString,16);
+ BrandIdString[MAXIMUM_CPU_BRAND_STRING_LENGTH] = 0;
+
+ //
+ // Check for Match with Controllable TDP SKU list
+ //
+ for(CpuFamilyIndex = 0;CpuFamilyIndex < CtrlTdpSkuSize;CpuFamilyIndex++) {
+ if(EfiAsciiStrStr((CHAR8 *) BrandIdString, (CHAR8 *) CtrlTdpSku[CpuFamilyIndex].CpuFamily)) {
+ //
+ // If NoOfCpus=0xff ,all processors in the family are ULV skus
+ //
+ if(CtrlTdpSku[CpuFamilyIndex].NoOfCpus == 0xFF) {
+ CtrlTdpSkuDetected = 1;
+ DEBUG ((EFI_D_ERROR, "\n Found Control TDP SKU"));
+ break;
+ }
+ for(CpuModelIndex = 0;CpuModelIndex < CtrlTdpSku[CpuFamilyIndex].NoOfCpus; CpuModelIndex++) {
+ if(EfiAsciiStrStr((CHAR8 *) BrandIdString,(CHAR8 *) CtrlTdpSku[CpuFamilyIndex].CpuModel[CpuModelIndex])) {
+ CtrlTdpSkuDetected = 1;
+ DEBUG ((EFI_D_ERROR, "\n Found Control TDP SKU"));
+ break;
+ }
+ } // end of CpuModelIndex
+ break;
+ }
+ } // end of if CpuFamilyIndex
+
+ ///
+ /// Enable Controllable TDp when
+ /// Power Limt1 is less than Package Tdp
+ /// Min Power is Zero
+ ///
+ if (CpuPmConfig->pTurboSettings->PowerLimit1 != AUTO && (CpuPmConfig->pTurboSettings->PowerLimit1 * mProcessorPowerUnit) / mCustomPowerUnit < mPackageTdp
+ && (mPackageMinPower == 0) && (CtrlTdpSkuDetected == 1)){
+ mControllableTdpEnable = 1;
+ //
+ // For ControllableTDP enabled systems add fake P-State below LFM and set PPC as LFM
+ //
+ mMinBusRatio = mMinBusRatio - 1;
+ //
+ // Set TAR MSR to LFM-1 (Fake LFM)
+ //
+ TempMsr.Qword = AsmReadMsr64 (MSR_TURBO_ACTIVATION_RATIO);
+ TempMsr.Dwords.Low &= ~MSR_TURBO_ACTIVATION_RATIO_MASK;
+ TempMsr.Dwords.Low |= (UINT16)((mMinBusRatio) & MSR_TURBO_ACTIVATION_RATIO_MASK);
+ DEBUG ((EFI_D_INFO, "\n Wrting MSR_TURBO_ACTIVATION_RATIO : %x \n",TempMsr.Qword));
+ AsmWriteMsr64 (MSR_TURBO_ACTIVATION_RATIO, TempMsr.Qword);
+ }
+ return EFI_SUCCESS;
+}
+
diff --git a/ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtCommon.h b/ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtCommon.h
new file mode 100644
index 0000000..2ee19bd
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtCommon.h
@@ -0,0 +1,877 @@
+/** @file
+ This header file contains power management definitions specific to
+ Haswell processors.
+
+ Acronyms:
+ PPM - Processor Power Management
+ TM Thermal Monitor
+ IST Intel(R) Speedstep technology
+ HT Hyper-Threading Technology
+
+@copyright
+ Copyright (c) 2012-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 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
+
+**/
+#ifndef _POWER_MGMT_COMMON_H_
+#define _POWER_MGMT_COMMON_H_
+
+#include "EdkIIGlueDxe.h"
+#include "EfiScriptLib.h"
+#include "PowerMgmtDefinitions.h"
+#include "Cpu.h"
+#include "CpuAccess.h"
+#include "CpuPlatformLib.h"
+#include "BaseLibInternal.h"
+#include "PchAccess.h"
+#include "PchPlatformLib.h"
+#include "SaAccess.h"
+#include "AslUpdateLib.h"
+
+#include EFI_PROTOCOL_DEPENDENCY (BootScriptSave)
+#include EFI_PROTOCOL_DEPENDENCY (CpuPlatformPolicy)
+#include EFI_PROTOCOL_PRODUCER (PowerMgmtInitDone)
+#include EFI_PROTOCOL_CONSUMER (MpService)
+#include EFI_PROTOCOL_CONSUMER (LoadedImage)
+#include EFI_PROTOCOL_DEPENDENCY (AcpiSupport)
+#include EFI_PROTOCOL_DEPENDENCY (AcpiTable)
+#include EFI_GUID_DEFINITION (PowerMgmtAcpiTableStorage)
+#include EFI_PROTOCOL_PRODUCER (PpmGlobalNvsArea)
+
+#define HSW_ULT_PCH_POWER_LEVELS 0x3
+#define EXTENDED_PCH_POWER_LEVELS 0x4
+#define PM_CST_LVL2 0x14
+
+#define FADT_C3_LATENCY 57
+#define FADT_C3_LATENCY_DISABLED 1001
+
+#define NATIVE_PSTATE_LATENCY 10
+#define PSTATE_BM_LATENCY 10
+
+#define MP_TIMEOUT_FOR_STARTUP_ALL_APS 0 ///< Set 0 for BSP always wait for APs
+
+#define NO_CALIBRATE 0
+#define PCODE_CALIBRATE 1
+#define BIOS_CALIBRATE 2
+#define PCODE_BCLK_CALIBRATION_TIMEOUT 22
+
+///
+/// Limit the number of P-states to 16. Up to Windows 7, the OS allocates 1KB buffer for the PSS package.
+/// So the maximum number of P-state OS can handle is 19. This is not an OS issue. Having too many P-states
+/// is not good for the system performance.
+///
+#define FVID_MAX_STATES 16
+#define FVID_MIN_STEP_SIZE 1
+
+///
+/// Cpu Brandstring length
+///
+#define MAXIMUM_CPU_BRAND_STRING_LENGTH 48
+
+///
+/// Power Limit Level
+///
+#define PL12TimeWindowCovert 1
+#define PL3TimeWindowConvert 3
+//
+// Global variables
+//
+///
+/// CpuPlatformPolicy Revision
+///
+extern UINT8 mCpuPolicyRevision;
+
+extern POWER_MGMT_CONFIG *mCpuPmConfig; ///< Power Managment policy configurations
+extern EFI_CPUID_REGISTER mCpuid01; // CPUID 01 values
+//
+// Values for FVID table calculate.
+//
+extern UINT16 mTurboBusRatio;
+extern UINT16 mMaxBusRatio;
+extern UINT16 mMinBusRatio;
+extern UINT16 mProcessorFlavor;
+extern UINT16 mBspBootRatio;
+extern UINT16 mPackageTdp;
+extern UINT16 mPackageTdpWatt;
+extern UINT16 mCpuConfigTdpBootRatio;
+extern UINT16 mCustomPowerUnit;
+extern UINT16 mCpuCacheSize;
+///
+/// Fractional part of Processor Power Unit in Watts. (i.e. Unit is 1/mProcessorPowerUnit)
+///
+extern UINT8 mProcessorPowerUnit;
+///
+/// Fractional part of Processor Time Unit in seconds. (i.e Unit is 1/mProcessorTimeUnit)
+///
+extern UINT8 mProcessorTimeUnit;
+///
+/// Maximum allowed power limit value in TURBO_POWER_LIMIT_MSR and PRIMARY_PLANE_POWER_LIMIT_MSR
+/// in units specified by PACKAGE_POWER_SKU_UNIT_MSR
+///
+extern UINT16 mPackageMaxPower;
+///
+/// Minimum allowed power limit value in TURBO_POWER_LIMIT_MSR and PRIMARY_PLANE_POWER_LIMIT_MSR
+/// in units specified by PACKAGE_POWER_SKU_UNIT_MSR
+///
+extern UINT16 mPackageMinPower;
+extern UINT8 mControllableTdpEnable; ///< Controllable TDP Enable/Disable
+extern UINT8 mRatioLimitProgrammble; ///< Porgrammable Ratio Limit
+extern UINT8 mTdpLimitProgrammble; ///< Porgrammable TDP Limit
+
+extern PPM_GLOBAL_NVS_AREA_PROTOCOL *mPpmGlobalNvsAreaProtocol; ///< Ppm GlobalNvs Protocol
+extern EFI_MP_SERVICES_PROTOCOL *mMpService; ///< Mp Services Protocol
+
+//
+// Globals to support updating ACPI Tables
+//
+extern EFI_ACPI_SUPPORT_PROTOCOL *mAcpiSupport;
+extern EFI_ACPI_TABLE_PROTOCOL *mAcpiTable;
+extern EFI_ACPI_DESCRIPTION_HEADER *mCpu0IstTable;
+extern EFI_ACPI_DESCRIPTION_HEADER *mApIstTable;
+extern EFI_ACPI_DESCRIPTION_HEADER *mCpu0CstTable;
+extern EFI_ACPI_DESCRIPTION_HEADER *mApCstTable;
+extern EFI_ACPI_DESCRIPTION_HEADER *mCpuPmTable;
+extern EFI_ACPI_DESCRIPTION_HEADER *mCpu0TstTable;
+extern EFI_ACPI_DESCRIPTION_HEADER *mApTstTable;
+extern EFI_ACPI_DESCRIPTION_HEADER *mLakeTinyTable;
+extern EFI_ACPI_DESCRIPTION_HEADER *mCtdpTable;
+
+//
+// Structure Declarations
+//
+
+typedef struct _FVID_HEADER {
+ UINT32 Stepping; ///< Matches value returned by CPUID function 1
+ UINT16 MaxBusRatio; ///< Matches BUS_RATIO_MAX field in PERF_STS_MSR
+ UINT16 Gv3States; ///< Number of states of FVID (N)
+} FVID_HEADER;
+
+typedef struct _FVID_STATE {
+ UINT32 State; ///< State Number (0 - N-1)
+ UINT16 BusRatio; ///< BUS_RATIO_SEL value to be written to PERF_CTL
+ UINT32 Power; ///< Typical power consumed by CPU in this state
+} FVID_STATE;
+
+typedef union _FVID_TABLE {
+ FVID_HEADER FvidHeader;
+ FVID_STATE FvidState;
+ UINT64 FvidData;
+} FVID_TABLE;
+
+typedef struct _ENABLE_CSTATE_PARAMS {
+ UINT16 C3IoAddress;
+} ENABLE_CSTATE_PARAMS;
+
+typedef struct _ENABLE_EMTTM_PARAMS {
+ FVID_TABLE *FvidPointer;
+} ENABLE_EMTTM_PARAMS;
+
+typedef struct _PCODE_BCLK_CALIBRATION_MAILBOX {
+ UINT32 PCalFactor;
+ UINT32 TSC24_L1;
+ UINT32 TSC24_L2;
+ UINT32 TSC24_U1;
+ UINT32 TSC24_U2;
+ UINT32 TSC100_L1;
+ UINT32 TSC100_L2;
+ UINT32 TSC100_U1;
+ UINT32 TSC100_U2;
+} PCODE_BCLK_CALIBRATION_MAILBOX;
+
+///
+/// ASL SSDT structure layout
+///
+#pragma pack(1)
+typedef struct {
+ UINT8 NameOp; ///< First opcode is a NameOp.
+ UINT32 NameString; ///< 'TDSS' ; Name of object.
+ UINT8 PackageOp; ///< db 12h ; Sixth OpCode is PackageOp.
+ UINT16 PackageLen; ///< dw 0h ; Seventh/Eighth OpCode is PackageLength.
+ UINT8 PackageEntryNum; ///< db 0Ch ; Ninth OpCode is number of package entries.
+ UINT8 StringPrefix1; ///< 0Dh
+ UINT64 Cpu0IstStr; ///< 00h
+ UINT8 StringNull1; ///< 00h
+ UINT8 DwordPrefix1a; ///< 0Ch
+ UINT32 Cpu0IstAddr; ///< 00h
+ UINT8 DwordPrefix1b; ///< 0Ch
+ UINT32 Cpu0IstLen; ///< 00h
+ UINT8 StringPrefix2; ///< 0Dh
+ UINT64 Cpu1IstStr; ///< 00h
+ UINT8 StringNull2; ///< 00h
+ UINT8 DwordPrefix2a; ///< 0Ch
+ UINT32 ApIstAddr; ///< 00h
+ UINT8 DwordPrefix2b; ///< 0Ch
+ UINT32 ApIstLen; ///< 00h
+ UINT8 StringPrefix3; ///< 0Dh
+ UINT64 Cpu0CstStr; ///< 00h
+ UINT8 StringNull3; ///< 00h
+ UINT8 DwordPrefix3a; ///< 0Ch
+ UINT32 Cpu0CstAddr; ///< 00h
+ UINT8 DwordPrefix3b; ///< 0Ch
+ UINT32 Cpu0CstLen; ///< 00h
+ UINT8 StringPrefix4; ///< 0Dh
+ UINT64 ApCstStr; ///< 00h
+ UINT8 StringNull4; ///< 00h
+ UINT8 DwordPrefix4a; ///< 0Ch
+ UINT32 ApCstAddr; ///< 00h
+ UINT8 DwordPrefix4b; ///< 0Ch
+ UINT32 ApCstLen; ///< 00h
+} SSDT_LAYOUT;
+#pragma pack()
+
+///
+/// ASL PCTP structure layout
+///
+#pragma pack(1)
+typedef struct {
+ UINT8 RegDes; ///< Byte [0]=0x82:Register descriptor code
+ UINT16 RegLen; ///< Byte [2:1]=0x0C:Register descriptor length
+ UINT8 RegType; ///< Byte [3]=0x01:Register type (System IO)
+ UINT8 RegWidth; ///< Byte [4]=0x10:Register width (16-bit)
+ UINT8 RegBitOffst; ///< Byte [5]=0x00:Register bit offset (0)
+ UINT8 RegAccSize; ///< Byte [6]=0x00:Register access size (0)
+ UINT64 RegAddress; ///< Byte [14:7]=Register address
+ UINT16 EndTag; ///< Byte [16:15]=End tag
+} PCTP_LAYOUT;
+#pragma pack()
+
+typedef struct {
+ UINT16 SkuPackageTdp;
+ UINTN SkuIccMax;
+ UINTN MsrCtdpPowerLimit1;
+ UINTN MsrCtdpPowerLimit2;
+ UINTN CtdpUpPowerLimit1;
+ UINTN CtdpUpPowerLimit2;
+ UINTN CtdpNominalPowerLimit1;
+ UINTN CtdpNominalPowerLimit2;
+ UINTN CtdpDownPowerLimit1;
+ UINTN CtdpDownPowerLimit2;
+ UINTN Reserved;
+} PPM_CTDP_OVERRIDE_TABLE;
+
+///
+/// PL1 Thermal Control structure layout
+///
+typedef union {
+ struct {
+ UINT8 Disable:1; ///< [0] Disable
+ UINT8 Reserved:7; ///< [7:2] Reserved
+ UINT8 FloorIA; ///< [15:8] Percent Throttle for IA component 255-0; 255=0%, 0=100%
+ UINT8 FloorGT; ///< [23:16] Percent Throttle for GT component 255-0; 255=0%, 0=100%
+ UINT8 FloorPCH; ///< [31:24] Percent Throttle for PCH component 255-0; 255=0%, 0=100%
+ } Bits;
+ UINT32 Uint32;
+ } PL1_THERMAL_CONTROL;
+
+typedef struct _PPM_CTRL_TDP_SKU_TBL{
+ UINT8 CpuFamily[MAXIMUM_CPU_BRAND_STRING_LENGTH]; ///< Cpu Family Brand String
+ UINTN NoOfCpus; ///< Number of Cpus,FF mean all cpus matching CpuFamily string above
+ UINT8 CpuModel[20][MAXIMUM_CPU_BRAND_STRING_LENGTH]; ///< Processor Model Number
+} PPM_CTRL_TDP_SKU_TBL;
+
+//
+// FVID Table Information
+// Default FVID table
+// One header field plus states
+//
+extern UINT16 mNumberOfStates;
+extern FVID_TABLE mEmptyFvidTable[FVID_MAX_STATES + 1];
+extern FVID_TABLE *mFvidPointer;
+
+//
+// Function prototypes
+//
+/**
+ Initializes P States and Turbo Power management features
+**/
+VOID
+InitializePStates (
+ VOID
+ );
+
+/**
+ Initializes XE support in the processor.
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+**/
+VOID
+InitTurboRatioLimits (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ );
+
+/**
+ Initializes required structures for P-State table creation and enables GV3
+ support in the processor.
+
+ @param[in] FvidPointer Table to update, must be initialized.
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+**/
+VOID
+InitGv3 (
+ IN OUT FVID_TABLE *FvidPointer,
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ );
+
+/**
+ Enables GV3 support in a logical processor.
+
+ This function must be MP safe.
+
+ @param[in] Buffer Pointer to the function parameters passed in.
+
+ @retval EFI_SUCCESS
+**/
+VOID
+EFIAPI
+ApSafeEnableGv3 (
+ IN OUT VOID *Buffer
+ );
+
+/**
+ This function updates the table provided with the FVID data for the processor.
+ If CreateDefaultTable is TRUE, a minimam FVID table will be provided.
+ The maximum number of states must be greater then or equal to two.
+ The table should be initialized in such a way as for the caller to determine if the
+ table was updated successfully. This function should be deprecated in the future when
+ Release 8 is integrated in favor of the EIST protocol calculating FVID information.
+
+ @param[in] FvidPointer Pointer to a table to be updated
+ @param[in] MaxNumberOfStates Number of entries in the table pointed to by FvidPointer
+ @param[in] MinStepSize Minimum step size for generating the FVID table
+ @param[in] CreateDefaultTable Create default FVID table rather then full state support
+**/
+VOID
+InitFvidTable (
+ IN OUT FVID_TABLE *FvidPointer,
+ IN UINT16 MaxNumberOfStates,
+ IN UINT16 MinStepSize,
+ IN BOOLEAN CreateDefaultTable
+ );
+
+/**
+ Create an FVID table based on the algorithm provided by the BIOS writer's guide.
+
+ @param[in] FvidPointer Pointer to a table to be updated
+ @param[in] MaxNumberOfStates Number of entries in the table pointed to by FvidPointer
+
+ @retval EFI_SUCCESS FVID table created successfully.
+ @retval EFI_INVALID_PARAMETER The bus ratio range don't permit FVID table calculation;
+ a default FVID table should be constructed.
+**/
+EFI_STATUS
+CreateFvidTable (
+ IN OUT FVID_TABLE *FvidPointer,
+ IN UINT16 MaxNumberOfStates
+ );
+
+/**
+ Create default FVID table with max and min states only.
+
+ @param[in] FvidPointer Pointer to a table to be updated
+**/
+VOID
+CreateDefaultFvidTable (
+ IN OUT FVID_TABLE *FvidPointer
+ );
+
+/**
+ Initializes Energy efficient P-state feature.
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+**/
+VOID
+InitEnergyEfficientPState (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ );
+
+
+/**
+ Configures the Interrupt Redirection Mode Selection for Logical Interrupts.
+
+ @param[in] CpuPmConfig Pointer to PPM Policy structure.
+**/
+VOID
+InitPpmIrmConfiguration (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ );
+
+/**
+ Completes platform power management initialization
+ (1) Initializes the TSC update variables.
+ (2) Initializes the GV state for processors.
+ (3) Saves MSR state for S3
+ (4) Adds a callback (SMI) in S3 resume script to restore the MSR
+**/
+VOID
+PpmPostInit (
+ VOID
+ );
+
+/**
+ Set processor P state to HFM or LFM
+**/
+VOID
+SetBootPState (
+ VOID
+ );
+
+/**
+ Set processor P state to HFM or LFM.
+
+ @param[in] Buffer Unused
+
+ @retval EFI_SUCCESS Processor MSR setting is saved.
+**/
+VOID
+EFIAPI
+ApSafeSetBootPState (
+ IN OUT VOID *Buffer
+ );
+
+/**
+ Initializes C States Power management features
+**/
+VOID
+InitializeCState (
+ IN POWER_MGMT_CONFIG *CpuPmConfig
+ );
+
+/**
+ Disable/Enable the CState Pre-Wake Feature
+
+ @param[in] CpuPmConfig - Pointer to policy protocol instance
+**/
+VOID
+InitCstatePreWake (
+ IN POWER_MGMT_CONFIG *CpuPmConfig
+ );
+
+/**
+ BootScript for PCode Mailbox function for mailbox write commands.
+ This function will poll the mailbox interface for control, issue the command
+ during s3 resume
+
+ @param[IN] MailboxCommand,
+ @param[IN] MailboxData,
+**/
+VOID
+MailboxS3Write (
+ IN UINT32 MailboxCommand,
+ IN UINT32 MailboxData
+ );
+
+/**
+ Calibrate 24MHz BCLK support to reduce the power consumption in idle states.
+
+ @retval EFI_UNSUPPORTED Unrecognized 24MHz BCLK Calibration Type.
+ @retval EFI_SUCCESS Processor C-State 24MHz BCLK support calibrated successfully.
+**/
+EFI_STATUS
+CalibrateBclkForCStates (
+ VOID
+ );
+
+/**
+ Enables C-State support as specified by the input flags on all logical
+ processors and sets associated timing requirements in the chipset.
+
+ @param[in] This Pointer to the protocol instance
+ @param[in] C3IoAddress IO address to generate C3 states (PM base + 014 usually)
+**/
+VOID
+EnableCStates (
+ IN UINT16 C3IoAddress
+ );
+
+/**
+ Enable C-State support as specified by the input flags on a logical processor.
+ Configure BIOS C1 Coordination (SMI coordination)
+ Enable IO redirection coordination
+ Choose proper coordination method
+ Configure extended C-States
+
+ This function must be MP safe.
+
+ @param[in] Buffer Pointer to a ENABLE_CSTATE_PARAMS containing the necessary
+ information to enable C-States
+
+ @retval EFI_SUCCESS Processor C-State support configured successfully.
+**/
+VOID
+EFIAPI
+ApSafeEnableCStates (
+ IN OUT VOID *Buffer
+ );
+
+/**
+ This will perform Miscellaneous Power Management related programming.
+
+ @param[in] CtdpSupport Status of InitializeConfigurableTdp funtion
+**/
+VOID
+InitMiscFeatures (
+ EFI_STATUS CtdpSupport
+ );
+
+/**
+ CTDP BIOS settings Initialization(Msr)
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+ @param[in] FvidPointer Table to update, must be initialized.
+
+ @exception EFI_UNSUPPORTED Ctdp not supported
+ @retval EFI_SUCCESS Ctdp Settings Initialized successfully from MSRs
+**/
+EFI_STATUS
+InitializeConfigurableTdp (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ );
+
+/**
+ Configures PowerLimits and Config TDP values
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+**/
+VOID
+ConfigureCtdp (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ );
+
+/**
+ This will perform general thermal initialization other then TM1, TM2, or
+ PROCHOT# on all logical processors.
+
+ @param[in] This Pointer to the protocol instance
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+**/
+VOID
+InitThermal (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ );
+
+/**
+ This will perform enable thermal initialization. TM1, TM2 and adaptive thermal
+ throttling are enabled/disabled together.
+
+ This function must be MP safe.
+
+ @param[in] Buffer Pointer to the function parameters passed in.
+
+ @retval EFI_SUCCESS General thermal initialization completed successfully
+**/
+VOID
+EFIAPI
+ApSafeInitThermal (
+ IN OUT VOID *Buffer
+ );
+
+/**
+ Enables the bi-directional PROCHOT# signal.
+
+ @retval EFI_SUCCESS PROCHOT# configured successfully
+**/
+EFI_STATUS
+EnableProcHot (
+ VOID
+ );
+
+
+/**
+ Locks down all settings.
+
+ @param[in] CpuPmConfig Pointer to PPM Policy structure.
+**/
+VOID
+PpmLockDown (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ );
+
+/**
+ Lock MSR_PMG_CST_CONFIG
+ This function must be MP safe.
+
+ @param[in] Buffer Not used (needed for API compatibility)
+
+ @retval EFI_SUCCESS Processor C-State locked successfully.
+**/
+VOID
+EFIAPI
+ApSafeLockDown (
+ IN OUT VOID *Buffer
+ );
+
+/**
+ Runs the specified procedure on all logical processors, passing in the
+ parameter buffer to the procedure.
+
+ @param[in] Procedure The function to be run.
+ @param[in] Buffer Pointer to a parameter buffer.
+
+ @retval EFI_SUCCESS
+**/
+EFI_STATUS
+RunOnAllLogicalProcessors (
+ IN OUT EFI_AP_PROCEDURE Procedure,
+ IN OUT VOID *Buffer
+ );
+
+/**
+ Configures following fields of MSR 0x610 based on user configuration:
+ Configures Long duration Turbo Mode (power limit 1) power level and time window
+ Configures Short duration Turbo mode (power limit 2)
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+**/
+VOID
+ConfigurePowerLimits (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ );
+
+/**
+ Configures following fields of MSR 0x610 based on user configuration:
+ Configures Long duration Turbo Mode (power limit 1) power level and time window
+ Configures Short duration Turbo mode (power limit 2)
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+**/
+VOID
+ConfigurePowerLimitsNonConfigTdpSkus (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ );
+
+/**
+ Configures following fields of PL3 MSR 0x615 based on user configuration:
+ Configures PL 3 power level and time window
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+**/
+VOID
+ConfigurePL3PowerLimits (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ );
+
+/**
+ This will perform PowerLimit 1 algorithm will be used to control Thermal Throttling features
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+**/
+
+/**
+ This will perform PowerLimit 1 algorithm will be used to control Thermal Throttling features
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+**/
+VOID
+InitPl1ThermalControl (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ );
+
+/**
+ Configures following fields of MSR 0x618 based on user configuration:
+ Configures Long duration Turbo Mode (power limit 1) power level and time window for DDR domain
+ Configures Short duration Turbo mode (power limit 2)
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+**/
+VOID
+ConfigureDdrPowerLimits (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ );
+
+/**
+ Verify and fix Custom Power Limit values
+
+ @param[in] CustomPowerLimit Custom Power Limit value
+
+ @retval Verified Custom power limit value
+**/
+UINT16
+VerifyAndFixCustomPowerLimit (
+ IN UINT32 CustomPowerLimit,
+ IN UINT16 CustomPlUnit
+ );
+
+/**
+ Verify and fix Custom Ratio values
+ Custom Ratio should be between MaxTurboFrequency and LFM
+
+ @param[in] CustomPowerLimit Custom Power Limit value
+ @param[in] CustomPlUnit Custom Power Limit Unit
+
+ @retval Verified Custom Ratio value
+**/
+UINT8
+VerifyAndFixCustomRatio (
+ IN UINT8 CustomRatio
+ );
+
+/**
+ CTDP BIOS settings Initialization(From Msrs)
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+
+ @exception EFI_UNSUPPORTED Ctdp not supported
+ @retval EFI_SUCCESS Ctdp Settings Initialized successfully from MSRs
+**/
+EFI_STATUS
+InitConfigurableTdpSettings (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ );
+
+/**
+ Get Power Limit2 based on Power Limit1 on Config TDP
+
+ @param[in] PowerLimit1 Power Limit 1 Value
+
+ @retval Calculated Power Limit2 value
+**/
+UINT16
+GetCtdpPowerLimit2 (
+ IN UINT16 PowerLimit1
+ );
+
+/**
+ Custom Configurable TDP Table BIOS Initialization
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+
+ @exception EFI_UNSUPPORTED Custom Ctdp settings are not available
+ @retval EFI_SUCCESS Successfully Initialized Custom Ctdp Settings
+**/
+EFI_STATUS
+InitCustomConfigurableTdp (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ );
+
+/**
+ Configures following fields of MSR 0x610 based on user configuration:
+ - Configures Long duration Turbo Mode (power limit 1) power level and time window
+ - Configures Short duration turbo mode (power limit 2)
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+**/
+VOID
+InitPchPowerSharing (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ );
+
+/**
+ Private helper function to convert various Turbo Power Limit Time from Seconds to CPU units
+
+ @param[in] TimeInSeconds Time in seconds
+ @param[in] PowerLimitLevel Power Limit Level
+
+ @retval UINT8 Converted time in CPU units
+**/
+UINT8
+GetConvertedTime (
+ IN UINT32 TimeInSeconds,
+ IN UINT8 PowerLimitLevel
+ );
+
+/**
+ Configures following fields of MSR 0x610
+ Configures Long duration Turbo Mode (power limit 1) power level and time window
+ Configures Short duration turbo mode (power limit 2)
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+**/
+VOID
+ConfigureCtdpPowerLimits (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ );
+
+/**
+ Patch Fvid Table with Ctdp Tar ratio and Tar-1 Ratio
+
+ @param[in] FvidPointer Pointer to Fvid Table
+**/
+VOID
+CtdpPatchFvidTable (
+ IN OUT FVID_TABLE *FvidPointer
+ );
+
+/**
+ Replace P state with given ratio
+
+ @param[in] FvidPointer Pointer to Fvid Table
+ @param[in] PssIndex FVID table index of P state to be replaced
+ @param[in] Ratio Target Ratio to put in
+**/
+VOID
+CtdpReplaceFvidRatio (
+ IN OUT FVID_TABLE *FvidPointer,
+ UINTN PssIndex,
+ UINTN Ratio
+ );
+
+/**
+ Patch the native _PSS package with the GV3 values
+ Uses ratio/VID values from the FVID table to fix up the control values in the _PSS.
+
+ (1) Find _PSS package:
+ (1.1) Find the _PR_CPU0 scope.
+ (1.2) Save a pointer to the package length.
+ (1.3) Find the _PSS AML name object.
+ (2) Resize the _PSS package.
+ (3) Fix up the _PSS package entries
+ (3.1) Check Turbo mode support.
+ (3.2) Check Dynamic FSB support.
+ (4) Fix up the Processor block and \_PR_CPU0 Scope length.
+ (5) Update SSDT Header with new length.
+
+ @retval EFI_SUCCESS
+ @retval EFI_NOT_FOUND - If _PR_.CPU0 scope is not foud in the ACPI tables
+**/
+EFI_STATUS
+AcpiPatchPss (
+ VOID
+ );
+
+/**
+ Configure the FACP for C state support
+**/
+VOID
+ConfigureFadtCStates (
+ VOID
+ );
+
+/**
+ Locate the PPM ACPI tables data file and read ACPI SSDT tables.
+ Publish the appropriate SSDT based on current configuration and capabilities.
+
+ @param[in] This Pointer to the protocol instance
+
+ @retval EFI_SUCCESS - on success
+ @retval Appropiate failure code on error
+**/
+EFI_STATUS
+InitializePpmAcpiTable (
+ VOID
+ );
+
+/**
+ Check for Ctrl TDP enabled SKUs and enable Controllable TDP
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+
+ @exception EFI_UNSUPPORTED Controllable TDP not Supported
+ @retval EFI_SUCCESS Controllable TDP Supported
+**/
+EFI_STATUS
+InitControllableTdp (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ );
+#endif
diff --git a/ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtDxe.cif b/ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtDxe.cif
new file mode 100644
index 0000000..99b6d76
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtDxe.cif
@@ -0,0 +1,19 @@
+<component>
+ name = "PowerMgmtInit"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\PowerManagement\Dxe"
+ RefName = "PowerMgmtInit"
+[files]
+"PowerMgmtDxe.mak"
+"PowerMgmtDxe.sdl"
+"PowerMgmtDxe.inf"
+"PowerMgmtDxe.dxs"
+"PowerMgmtInit.c"
+"IdleStates.c"
+"MiscFunctions.c"
+"PerformanceStates.c"
+"PowerLimits.c"
+"Thermal.c"
+"PowerMgmtCommon.h"
+"PowerMgmtInit.h"
+<endComponent>
diff --git a/ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtDxe.dxs b/ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtDxe.dxs
new file mode 100644
index 0000000..199a064
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtDxe.dxs
@@ -0,0 +1,38 @@
+/** @file
+ Dependency expression source file.
+
+@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 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
+
+**/
+
+
+#include "EfiDepex.h"
+
+#include EFI_PROTOCOL_DEFINITION (MpService)
+#include EFI_PROTOCOL_DEPENDENCY (BootScriptSave)
+#include EFI_PROTOCOL_DEPENDENCY (AcpiSupport)
+#include EFI_PROTOCOL_DEPENDENCY (CpuPlatformPolicy)
+#include EFI_PROTOCOL_DEPENDENCY (GlobalNvsArea)
+
+DEPENDENCY_START
+ EFI_BOOT_SCRIPT_SAVE_PROTOCOL_GUID AND
+ EFI_ACPI_SUPPORT_GUID AND
+ EFI_MP_SERVICES_PROTOCOL_GUID AND
+ EFI_GLOBAL_NVS_AREA_PROTOCOL_GUID AND
+ DXE_CPU_PLATFORM_POLICY_PROTOCOL_GUID
+DEPENDENCY_END
diff --git a/ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtDxe.inf b/ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtDxe.inf
new file mode 100644
index 0000000..4eb4666
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtDxe.inf
@@ -0,0 +1,114 @@
+## @file
+# Component description file for Power Management module
+#
+#@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 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
+#
+
+[defines]
+BASE_NAME = PowerMgmtDxe
+FILE_GUID = f7731b4c-58a2-4df4-8980-5645d39ece58
+COMPONENT_TYPE = BS_DRIVER
+
+[sources.common]
+ PowerMgmtinit.h
+ PowerMgmtinit.c
+ PowerMgmtCommon.h
+ PerformanceStates.c
+ IdleStates.c
+ PowerLimits.c
+ Thermal.c
+ MiscFunctions.c
+
+#
+# Edk II Glue Driver Entry Point
+#
+ EdkIIGlueDxeDriverEntryPoint.c
+
+[includes.common]
+ .
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Library/BaseLib
+ $(EFI_SOURCE)
+ $(EFI_SOURCE)/Framework
+ $(EFI_SOURCE)/Include
+ $(EFI_SOURCE)/Include/IndustryStandard
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_SA_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_SA_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include/Library
+#
+# Typically the sample code referenced will be available in the code base already
+# So keep this include at the end to defer to the source base definition
+# and only use the sample code definition if source base does not include these files.
+#
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/SampleCode
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/SampleCode/Include
+
+[libraries.common]
+ CpuGuidLib
+ CpuProtocolLib
+ DxeAslUpdateLib
+ EfiProtocolLib
+ EdkFrameworkProtocolLib
+ EdkIIGlueBaseLib
+ EdkIIGlueBaseIoLibIntrinsic
+ EdkIIGlueBaseMemoryLib
+ EdkIIGlueDxeMemoryAllocationLib
+ EdkIIGlueDxeDebugLibReportStatusCode
+ EdkIIGlueDxeReportStatusCodeLib
+ EdkIIGlueUefiBootServicesTableLib
+ EdkIIGlueUefiRuntimeServicesTableLib
+ EdkIIGlueUefiDevicePathLib
+ EfiScriptLib
+ EdkProtocolLib
+ CpuPlatformLib
+ EfiCommonLib
+
+[libraries.ia32,libraries.x64]
+ CpuIa32Lib
+
+[nmake.common]
+ IMAGE_ENTRY_POINT = _ModuleEntryPoint
+ DPX_SOURCE = PowerMgmtDxe.dxs
+#
+# Module Entry Point
+#
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=InitializePowerManagement
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_BASE_LIB__ \
+ -D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ -D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ -D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \
+ -D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ -D __EDKII_GLUE_DXE_REPORT_STATUS_CODE_LIB__ \
+ -D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_UEFI_DEVICE_PATH_LIB__
diff --git a/ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtDxe.mak b/ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtDxe.mak
new file mode 100644
index 0000000..3c65a6b
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtDxe.mak
@@ -0,0 +1,82 @@
+# MAK file for the eModule:PowerManagement
+
+EDK : PowerMgmtDxe
+
+BUILD_PowerMgmtDxe_DIR = $(BUILD_DIR)\$(PowerMgmtDxe_DIR)
+
+$(BUILD_DIR)\PowerMgmtDxe.mak : $(PowerMgmtDxe_DIR)\PowerMgmtDxe.cif $(BUILD_RULES)
+ $(CIF2MAK) $(PowerMgmtDxe_DIR)\PowerMgmtDxe.cif $(CIF2MAK_DEFAULTS)
+
+PowerMgmtDxe : $(BUILD_DIR)\PowerMgmtDxe.MAK PowerMgmtDxeBin
+
+PowerMgmtDxe_OBJECTS = \
+ $(BUILD_PowerMgmtDxe_DIR)\IdleStates.obj \
+ $(BUILD_PowerMgmtDxe_DIR)\MiscFunctions.obj \
+ $(BUILD_PowerMgmtDxe_DIR)\PerformanceStates.obj \
+ $(BUILD_PowerMgmtDxe_DIR)\PowerLimits.obj \
+ $(BUILD_PowerMgmtDxe_DIR)\Thermal.obj \
+ $(BUILD_PowerMgmtDxe_DIR)\PowerMgmtInit.obj
+
+PowerMgmtDxe_MY_INCLUDES= \
+ $(EdkIIGlueLib_INCLUDES)\
+ /I$(EdkIIGlueBaseLib_DIR)\
+ $(EDK_INCLUDES)\
+ $(PROJECT_CPU_INCLUDES)\
+ $(INTEL_PCH_INCLUDES)\
+ $(INTEL_MCH_INCLUDES)\
+ $(INTEL_PLATFORM_PROTOCOL_INCLUDES)
+
+PowerMgmtDxe_DEFINES = $(MY_DEFINES)\
+ /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=InitializePowerManagement"\
+ /D __EDKII_GLUE_BASE_LIB__ \
+ /D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ /D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ /D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \
+ /D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ /D __EDKII_GLUE_DXE_REPORT_STATUS_CODE_LIB__ \
+ /D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \
+ /D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__ \
+ /D __EDKII_GLUE_UEFI_DEVICE_PATH_LIB__
+
+PowerMgmtDxe_LIBS =\
+ $(EFIGUIDLIB)\
+ $(EDKFRAMEWORKPROTOCOLLIB)\
+ $(EDKPROTOCOLLIB)\
+ $(EFISCRIPTLIB)\
+ $(EdkIIGlueBaseIoLibIntrinsic_LIB)\
+ $(EdkIIGlueBaseLib_LIB)\
+ $(EdkIIGlueBaseMemoryLib_LIB)\
+ $(EdkIIGlueDxeReportStatusCodeLib_LIB)\
+ $(EdkIIGlueDxeServicesTableLib_LIB)\
+ $(EdkIIGlueDxeDebugLibReportStatusCode_LIB)\
+ $(EdkIIGlueUefiBootServicesTableLib_LIB)\
+ $(EdkIIGlueUefiLib_LIB)\
+ $(EdkIIGlueBasePciLibPciExpress_LIB)\
+ $(EdkIIGlueDxeMemoryAllocationLib_LIB)\
+ $(EdkIIGlueBaseTimerLibLocalApic_LIB)\
+ $(EdkIIGlueDxeHobLib_LIB)\
+ $(EdkIIGlueHiiLib_LIB)\
+ $(EFIDRIVERLIB)\
+ $(UEFIEFIIFRSUPPORTLIB)\
+ $(CpuProtocolLib_LIB)\
+ $(CpuGuidLib_LIB)\
+ $(PchPlatformDxeLib_LIB)\
+ $(CpuPlatformLib_LIB)\
+ $(PpmAslUpdateLib_LIB)
+
+
+PowerMgmtDxeBin : $(PowerMgmtDxe_LIBS)
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\PowerMgmtDxe.mak all\
+ NAME=PowerMgmtDxe\
+ MAKEFILE=$(BUILD_DIR)\PowerMgmtDxe.mak \
+ "MY_INCLUDES=$(PowerMgmtDxe_MY_INCLUDES)" \
+ "MY_DEFINES=$(PowerMgmtDxe_DEFINES)"\
+ OBJECTS="$(PowerMgmtDxe_OBJECTS)" \
+ GUID=f7731b4c-58a2-4df4-8980-5645d39ece58\
+ ENTRY_POINT=_ModuleEntryPoint \
+ TYPE=RT_DRIVER \
+ EDKIIModule=DXEDRIVER\
+ DEPEX1=$(PowerMgmtDxe_DIR)\PowerMgmtDxe.dxs \
+ DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX \
+ COMPRESS=1
diff --git a/ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtDxe.sdl b/ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtDxe.sdl
new file mode 100644
index 0000000..af4c594
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtDxe.sdl
@@ -0,0 +1,25 @@
+TOKEN
+ Name = "Haswell_PowerMgmtDxe_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable Cpu Pei init support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+End
+
+PATH
+ Name = "PowerMgmtDxe_DIR"
+End
+
+MODULE
+ Help = "Includes PowerMgmtDxe.mak to Project"
+ File = "PowerMgmtDxe.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\PowerMgmtDxe.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End
diff --git a/ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtInit.c b/ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtInit.c
new file mode 100644
index 0000000..414167d
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtInit.c
@@ -0,0 +1,840 @@
+/** @file
+ Processor Power Management initialization code. This code determines current
+ user configuration and modifies and loads ASL as well as initializing chipset
+ and processor features to enable the proper power management.
+
+ Acronyms:
+ PPM - Processor Power Management
+ TM - Thermal Monitor
+ IST - Intel(R) Speedstep technology
+ HT - Hyper-Threading Technology
+
+@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 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
+
+**/
+
+#include "PowerMgmtInit.h"
+
+//
+// Global variables
+//
+#include <Protocol\GlobalNvsArea\GlobalNvsArea.h> // <<<<
+///
+/// Power Managment policy configurations
+///
+POWER_MGMT_CONFIG *mCpuPmConfig = NULL;
+EFI_CPUID_REGISTER mCpuid01 = { 0, 0, 0, 0 }; // CPUID 01 values
+//
+// Values for FVID table calculate.
+//
+UINT16 mTurboBusRatio = 0;
+UINT16 mMaxBusRatio = 0;
+UINT16 mMinBusRatio = 0;
+UINT16 mProcessorFlavor = 0;
+UINT16 mBspBootRatio = 0;
+UINT16 mPackageTdp = 0; ///< Processor TDP value in MSR_PACKAGE_POWER_SKU.
+UINT16 mPackageTdpWatt = 0; ///< Processor TDP value in Watts.
+UINT16 mCpuConfigTdpBootRatio = 0; ///< Config TDP Boot settings
+UINT16 mCustomPowerUnit = 1;
+UINT16 mCpuCacheSize = 0; ///< Cache Size in KB
+UINT8 mCpuPolicyRevision = 0;
+DXE_CPU_PLATFORM_POLICY_PROTOCOL *mCpuPlatformPolicy = NULL;
+
+///
+/// Fractional part of Processor Power Unit in Watts. (i.e. Unit is 1/mProcessorPowerUnit)
+///
+UINT8 mProcessorPowerUnit = 0;
+///
+/// Maximum allowed power limit value in TURBO_POWER_LIMIT_MSR and PRIMARY_PLANE_POWER_LIMIT_MSR
+/// in units specified by PACKAGE_POWER_SKU_UNIT_MSR
+///
+UINT16 mPackageMaxPower = 0;
+///
+/// Minimum allowed power limit value in TURBO_POWER_LIMIT_MSR and PRIMARY_PLANE_POWER_LIMIT_MSR
+/// in units specified by PACKAGE_POWER_SKU_UNIT_MSR
+///
+UINT16 mPackageMinPower = 0;
+
+UINT8 mControllableTdpEnable = 0; ///< Controllable TDP enable/Disable
+UINT8 mRatioLimitProgrammble = 0; ///< Programmable Ratio Limit
+UINT8 mTdpLimitProgrammble = 0; ///< Porgrammable TDP Limit
+PPM_GLOBAL_NVS_AREA_PROTOCOL *mPpmGlobalNvsAreaProtocol = NULL; ///< Ppm GlobalNvs Protocol
+EFI_MP_SERVICES_PROTOCOL *mMpService = NULL; ///< Mp Services Protocol
+
+//
+// FVID Table Information
+// Default FVID table
+// One header field plus states
+//
+UINT16 mNumberOfStates = 0;
+FVID_TABLE mEmptyFvidTable[FVID_MAX_STATES + 1];
+FVID_TABLE *mFvidPointer = &mEmptyFvidTable[0];
+
+//
+// Globals to support updating ACPI Tables
+//
+EFI_ACPI_SUPPORT_PROTOCOL *mAcpiSupport = NULL;
+EFI_ACPI_TABLE_PROTOCOL *mAcpiTable = NULL;
+EFI_ACPI_DESCRIPTION_HEADER *mCpu0IstTable = NULL;
+EFI_ACPI_DESCRIPTION_HEADER *mApIstTable = NULL;
+EFI_ACPI_DESCRIPTION_HEADER *mCpu0CstTable = NULL;
+EFI_ACPI_DESCRIPTION_HEADER *mApCstTable = NULL;
+EFI_ACPI_DESCRIPTION_HEADER *mCpuPmTable = NULL;
+EFI_ACPI_DESCRIPTION_HEADER *mCpu0TstTable = NULL;
+EFI_ACPI_DESCRIPTION_HEADER *mApTstTable = NULL;
+EFI_ACPI_DESCRIPTION_HEADER *mLakeTinyTable = NULL;
+EFI_ACPI_DESCRIPTION_HEADER *mCtdpTable = NULL;
+
+/**
+ Initialize the power management support.
+ This function will do boot time configuration:
+ Detect HW capabilities and SW configuration
+ Initialize HW and software state (primarily MSR and ACPI tables)
+
+ @param[in] ImageHandle Pointer to the loaded image protocol for this driver
+ @param[in] SystemTable Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS The driver installes/initialized correctly.
+ @retval Driver will ASSERT in debug builds on error. PPM functionality is considered critical for mobile systems.
+**/
+EFI_STATUS
+InitializePowerManagement (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+ PPM_GLOBAL_NVS_AREA_PROTOCOL PpmGlobalNvsAreaProtocol;
+ EFI_GUID EfiPpmGlobalNvsAreaProtocolGuid = EFI_PPM_GLOBAL_NVS_AREA_PROTOCOL_GUID;
+
+ Handle = NULL;
+
+ ///
+ /// Locate platform configuration information
+ ///
+ Status = gBS->LocateProtocol (&gDxeCpuPlatformPolicyProtocolGuid, NULL, (VOID **) &mCpuPlatformPolicy);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Initialize the Global pointer for Power Managment Platform policy
+ ///
+ mCpuPmConfig = mCpuPlatformPolicy->PowerMgmtConfig;
+
+ Status = (gBS->AllocatePool) (EfiACPIMemoryNVS, sizeof (PPM_GLOBAL_NVS_AREA), (VOID **) &PpmGlobalNvsAreaProtocol.Area);
+ ASSERT_EFI_ERROR (Status);
+ ZeroMem ((VOID *) PpmGlobalNvsAreaProtocol.Area, sizeof (PPM_GLOBAL_NVS_AREA));
+
+ PpmGlobalNvsAreaProtocol.Area->Revision = PPM_GLOBAL_NVS_AREA_REVISION_1;
+ PpmGlobalNvsAreaProtocol.Area->MiscPowerManagementFlags |= mCpuPmConfig->pFunctionEnables->LakeTiny;
+
+ ///
+ /// Install Cpu Power management GlobalNVS Area protocol
+ ///
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &EfiPpmGlobalNvsAreaProtocolGuid,
+ &PpmGlobalNvsAreaProtocol,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DumpCpuPmConfig ();
+
+ ///
+ /// Locate the S3 resume scripting protocol
+ ///
+ INITIALIZE_SCRIPT (ImageHandle, SystemTable);
+
+ ///
+ /// Initialize Power management Global variables
+ ///
+ InitializePowerManagementGlobalVariables ();
+
+ ///
+ /// Initialize CPU Power management code (determine HW and configured state, configure hardware and software accordingly)
+ ///
+ Status = InitializePpm ();
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Install the PowerMgmtInitDone Protocol so that PowerMgmtS3 driver can load to save the MSRs for S3 resume
+ ///
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gEfiPowerMgmtInitDoneProtocolGuid,
+ NULL,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Initializes the platform power management global variable.
+ This must be called prior to any of the functions being used.
+
+ @retval EFI_SUCCESS Library was initialized successfully
+ @retval EFI_DEVICE_ERROR If CPU is not supported by this library
+**/
+VOID
+InitializePowerManagementGlobalVariables (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ MSR_REGISTER TempMsr;
+ MSR_REGISTER PackagePowerSKUUnitMsr;
+ MSR_REGISTER PlatformInfoMsr;
+ EFI_GUID EfiMpServiceProtocolGuid = EFI_MP_SERVICES_PROTOCOL_GUID;
+ UINT16 Associativity;
+ UINT16 CachePartitions;
+ UINT16 CacheLineSize;
+ UINT16 CacheNumberofSets;
+ EFI_CPUID_REGISTER Cpuid04;
+// >>>>
+ EFI_GLOBAL_NVS_AREA_PROTOCOL *GlobalNvsArea;
+ EFI_GUID gEfiGlobalNvsAreaProtocolGuid = EFI_GLOBAL_NVS_AREA_PROTOCOL_GUID;
+// <<<<
+ //
+ // Read the CPUID information
+ //
+ AsmCpuid (CPUID_VERSION_INFO, &mCpuid01.RegEax, &mCpuid01.RegEbx, &mCpuid01.RegEcx, &mCpuid01.RegEdx);
+
+ ///
+ /// Locate Ppm GlobalNvs Protocol.
+ ///
+ Status = gBS->LocateProtocol (
+ &gPpmGlobalNvsAreaProtocolGuid,
+ NULL,
+ (VOID **) &mPpmGlobalNvsAreaProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Ppm GloableNvs protocol not found"));
+ }
+ ASSERT_EFI_ERROR (Status);
+ if (mPpmGlobalNvsAreaProtocol != NULL) {
+ mPpmGlobalNvsAreaProtocol->Area->Cpuid = GetCpuFamily() | GetCpuStepping();
+ }
+
+ ///
+ /// Locate MP service protocol
+ ///
+ Status = gBS->LocateProtocol (
+ &EfiMpServiceProtocolGuid,
+ NULL,
+ (VOID **) &mMpService
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Get Platform ID by reading System Agent's Device ID (B0:D0:F0:R02)
+ ///
+ mProcessorFlavor = McD0PciCfg16 (R_SA_MC_DEVICE_ID);
+
+ //
+ // Read the CPUID4 information for LLC size
+ //
+ AsmCpuidEx (CPUID_FUNCTION_4, 0x3, &Cpuid04.RegEax, &Cpuid04.RegEbx, &Cpuid04.RegEcx, &Cpuid04.RegEdx);
+ //
+ // Determine Cache Size in Kilo Bytes
+ // This Cache Size in Bytes = (Associativity) * (Partitions + 1) * (Line_Size + 1) * (Sets + 1)
+ // = (EBX[31:22] + 1) * (EBX[21:12] + 1) * (EBX[11:0] + 1) * (ECX + 1)
+ //
+ Associativity = (UINT16) (((Cpuid04.RegEbx >> 22) & CPU_CACHE_ASSOCIATIVITY_MASK) + 1);
+ CachePartitions = (UINT16) (((Cpuid04.RegEbx >> 12) & CPU_CACHE_PARTITION_MASK) + 1);
+ CacheLineSize = (UINT16) (((UINT16) Cpuid04.RegEbx & CPU_CACHE_LINE_SIZE_MASK) + 1);
+ CacheNumberofSets = (UINT16) (Cpuid04.RegEcx + 1);
+ mCpuCacheSize = (UINT16) ((Associativity * CachePartitions * CacheLineSize * CacheNumberofSets) / 1024);
+ ///
+ /// Get Maximum Non-Turbo bus ratio (HFM) from Platform Info MSR Bits[15:8]
+ ///
+ PlatformInfoMsr.Qword = AsmReadMsr64 (MSR_PLATFORM_INFO);
+ mMaxBusRatio = PlatformInfoMsr.Bytes.SecondByte;
+ ///
+ /// Get Maximum Efficiency bus ratio (LFM) from Platform Info MSR Bits[47:40]
+ ///
+ mMinBusRatio = PlatformInfoMsr.Bytes.SixthByte;
+ ///
+ /// Get Max Turbo Ratio from Turbo Ratio Limit MSR Bits [7:0]
+ ///
+ TempMsr.Qword = AsmReadMsr64 (MSR_TURBO_RATIO_LIMIT);
+ mTurboBusRatio = (UINT16) (TempMsr.Dwords.Low & B_MSR_TURBO_RATIO_LIMIT_1C);
+ ///
+ /// Check if Turbo Ratio Limit is programmable
+ /// Platform Info MSR (0xCE) [28]
+ ///
+ mRatioLimitProgrammble = (UINT8) RShiftU64 ((PlatformInfoMsr.Qword & B_PLATFORM_INFO_RATIO_LIMIT), 28);
+ ///
+ /// Check if TDP Limit is programmable
+ /// Platform Info MSR (0xCE) [29]
+ ///
+ mTdpLimitProgrammble = (UINT8) RShiftU64 ((PlatformInfoMsr.Qword & B_PLATFORM_INFO_TDC_TDP_LIMIT), 29);
+
+ ///
+ /// Get Processor TDP
+ /// Get Maximum Power from Turbo Power Limit MSR Bits[14:0]
+ /// and convert it to units specified by Package Power SKU
+ /// Unit MSR [3:0]
+ ///
+ TempMsr.Qword = EfiReadMsr (MSR_PACKAGE_POWER_SKU);
+ PackagePowerSKUUnitMsr.Qword = EfiReadMsr (MSR_PACKAGE_POWER_SKU_UNIT);
+ mProcessorPowerUnit = (PackagePowerSKUUnitMsr.Bytes.FirstByte & PACKAGE_POWER_UNIT_MASK);
+ if (mProcessorPowerUnit == 0) {
+ mProcessorPowerUnit = 1;
+ } else {
+ mProcessorPowerUnit = (UINT8) LShiftU64 (2, (mProcessorPowerUnit - 1));
+ }
+ mPackageTdp = (TempMsr.Dwords.Low & PACKAGE_TDP_POWER_MASK);
+ mPackageTdpWatt = (UINT16) DivU64x32 (mPackageTdp , mProcessorPowerUnit);
+ mPackageMaxPower = (UINT16) (TempMsr.Dwords.High & PACKAGE_MAX_POWER_MASK);
+ mPackageMinPower = (UINT16) RShiftU64 ((TempMsr.Dwords.Low & PACKAGE_MIN_POWER_MASK), 16);
+ mCpuPolicyRevision = mCpuPlatformPolicy->Revision;
+
+ ///
+ /// Set mCustomPowerUnit to user selected Power unit
+ ///
+ mCustomPowerUnit = 1;
+ if ((mCpuPlatformPolicy->Revision >= DXE_PLATFORM_CPU_POLICY_PROTOCOL_REVISION_6 )
+ && (mCpuPmConfig->CustomPowerUnit == PowerUnit125MilliWatts)) {
+ mCustomPowerUnit = 8; ///< Unit is 125 milli watt
+ }
+
+ ///
+ /// If specified, create a custom the FVID table.
+ /// (The settings populating the FVID table may not be correct for the
+ /// specific processor, and it is up to the user to specify settings
+ /// applicable to the processor being used.)
+ ///
+ ZeroMem (mFvidPointer, sizeof (mEmptyFvidTable));
+ if (mCpuPmConfig->pCustomRatioTable->NumberOfEntries >= 2) {
+ CreateCustomFvidTable (mFvidPointer);
+ }
+
+ ///
+ /// Initialize flags based on processor capablities
+ ///
+ SetPpmFlags ();
+
+ ///
+ /// Determine current user configuration
+ ///
+ SetUserConfigurationPpmFlags ();
+
+// >>>>
+ //
+ // Locate the Global NVS Protocol.
+ //
+ Status = gBS->LocateProtocol (&gEfiGlobalNvsAreaProtocolGuid,
+ NULL, &GlobalNvsArea );
+ DEBUG((EFI_D_ERROR, "Status=gBS->LocateProtocol (&gEfiGlobalNvsAreaProtocolGuid) ===> %r !!!\n", Status));
+
+ if(!EFI_ERROR(Status)) {
+ GlobalNvsArea->Area->PpmFlags = mPpmGlobalNvsAreaProtocol->Area->PpmFlags;
+ }
+// <<<<
+ ///
+ /// Locate ACPI support protocol
+ ///
+ Status = gBS->LocateProtocol (&gEfiAcpiSupportProtocolGuid, NULL, (VOID **) &mAcpiSupport);
+ ASSERT_EFI_ERROR (Status);
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &mAcpiTable);
+ ASSERT_EFI_ERROR (Status);
+ return;
+}
+
+/**
+ Create a custom FVID table based on setup options.
+ Caller is responsible for providing a large enough table.
+
+ @param[in] FvidPointer Table to update, must be initialized.
+**/
+VOID
+CreateCustomFvidTable (
+ IN OUT FVID_TABLE *FvidPointer
+ )
+{
+ UINT16 Index;
+
+ ///
+ /// BWG Section 14.6.2 Determining Number of Operating Points
+ /// It is recommended that system BIOS limit the number of P states to 16
+ ///
+ if (mCpuPmConfig->pCustomRatioTable->NumberOfEntries > FVID_MAX_STATES) {
+ DEBUG (
+ (EFI_D_WARN,
+ "VidNumber(%d) is greater than maximum(%d) supported.",
+ mCpuPmConfig->pCustomRatioTable->NumberOfEntries,
+ FVID_MAX_STATES)
+ );
+ mCpuPmConfig->pCustomRatioTable->NumberOfEntries = FVID_MAX_STATES;
+ }
+ ///
+ /// Fill in the table header
+ ///
+ FvidPointer[0].FvidHeader.Stepping = mCpuPmConfig->pCustomRatioTable->Cpuid;
+ FvidPointer[0].FvidHeader.MaxBusRatio = mCpuPmConfig->pCustomRatioTable->MaxRatio;
+ FvidPointer[0].FvidHeader.Gv3States = mCpuPmConfig->pCustomRatioTable->NumberOfEntries;
+ ///
+ /// Fill in the state data
+ ///
+ for (Index = 0; Index < mCpuPmConfig->pCustomRatioTable->NumberOfEntries; Index++) {
+ FvidPointer[Index + 1].FvidState.State = Index;
+ FvidPointer[Index + 1].FvidState.BusRatio = mCpuPmConfig->pCustomRatioTable->StateRatio[Index];
+ }
+}
+
+/**
+ Set the PPM flags specific to Haswell processors
+
+ @retval EFI_SUCCESS PpmFlags updated with the features supported by the processor
+**/
+VOID
+SetPpmFlags (
+ VOID
+ )
+{
+ MSR_REGISTER CoreThreadCount;
+ MSR_REGISTER Ia32MiscEnable;
+ EFI_CPUID_REGISTER Cpuid01;
+ EFI_CPUID_REGISTER Cpuid05;
+ EFI_CPUID_REGISTER Cpuid06;
+ UINTN States;
+ BOOLEAN CpuidLimitingEnabled;
+ UINT32 PpmFlags;
+
+ ZeroMem (&Cpuid01, sizeof (Cpuid01));
+ ZeroMem (&Cpuid05, sizeof (Cpuid05));
+ ZeroMem (&Cpuid06, sizeof (Cpuid06));
+ PpmFlags = 0;
+
+ ///
+ /// Check if the processor has multiple cores
+ ///
+ CoreThreadCount.Qword = AsmReadMsr64 (MSR_CORE_THREAD_COUNT);
+ if ((CoreThreadCount.Dwords.Low & B_THREAD_COUNT_MASK) > 1) {
+ PpmFlags |= PPM_CMP;
+ }
+ if (mCpuid01.RegEdx & B_CPUID_VERSION_INFO_EDX_TM1) { ///< Check TM capable and update the flag
+ PpmFlags |= PPM_TM;
+ }
+ ///
+ /// Check EIST capable. If EIST capable, also set the boot P-state to HFM flag.
+ ///
+ if (mCpuid01.RegEcx & B_CPUID_VERSION_INFO_ECX_EIST) {
+ PpmFlags |= (PPM_EIST);
+ DEBUG ((EFI_D_INFO, "GV3 capable\n"));
+ }
+ ///
+ /// Disable CPUID limiting (and save current setting) if enabled
+ /// and enable MONITOR/MWAIT support
+ ///
+ Ia32MiscEnable.Qword = AsmReadMsr64 (MSR_IA32_MISC_ENABLE);
+ CpuidLimitingEnabled = (BOOLEAN) (Ia32MiscEnable.Qword & B_MSR_IA32_MISC_ENABLE_CPUID_MAX);
+ if (CpuidLimitingEnabled) {
+ Ia32MiscEnable.Qword &= ~B_MSR_IA32_MISC_ENABLE_CPUID_MAX;
+ }
+ AsmWriteMsr64 (MSR_IA32_MISC_ENABLE, Ia32MiscEnable.Qword);
+ ///
+ /// Read the CPUID values we care about. We cannot use the stored
+ /// values because they may have changes since we disabled limiting
+ /// and enabled MONITOR/MWAIT
+ ///
+ AsmCpuid (1, &Cpuid01.RegEax, &Cpuid01.RegEbx, &Cpuid01.RegEcx, &Cpuid01.RegEdx);
+ AsmCpuid (5, &Cpuid05.RegEax, &Cpuid05.RegEbx, &Cpuid05.RegEcx, &Cpuid05.RegEdx);
+ AsmCpuid (6, &Cpuid06.RegEax, &Cpuid06.RegEbx, &Cpuid06.RegEcx, &Cpuid06.RegEdx);
+ ///
+ /// Determine if the MONITOR/MWAIT instructions are supported.
+ ///
+ if ((Cpuid01.RegEcx & B_CPUID_VERSION_INFO_ECX_MWAIT && Cpuid05.RegEcx & B_CPUID_MONITOR_MWAIT_ECX_EXTENSIONS)) {
+ PpmFlags |= PPM_MWAIT_EXT;
+ }
+ ///
+ /// Determine the C-State and Enhanced C-State support present.
+ /// Monitor/MWAIT parameters function describes the numbers supported.
+ ///
+ States = RShiftU64 (Cpuid05.RegEdx, 4) & 0xF;
+ if (States >= ENHANCED_CSTATE_SUPPORTED) {
+ PpmFlags |= PPM_C1 + PPM_C1E;
+ } else if (States == CSTATE_SUPPORTED) {
+ PpmFlags |= PPM_C1;
+ }
+ States = RShiftU64 (Cpuid05.RegEdx, 8) & 0xF;
+ if ((States >= CSTATE_SUPPORTED) && (PpmFlags & PPM_C1)) {
+ PpmFlags |= PPM_C3;
+ }
+ States = RShiftU64 (Cpuid05.RegEdx, 12) & 0xF;
+ if (States >= C6_C7_LONG_LATENCY_SUPPORTED) { // Both Long and Short Latency C6 supported
+ PpmFlags |= (PPM_C6 | C6_LONG_LATENCY_ENABLE);
+ } else if (States >= C6_C7_SHORT_LATENCY_SUPPORTED) { // Only Short Latency C6 supported.
+ PpmFlags |= PPM_C6;
+ }
+
+ States = RShiftU64 (Cpuid05.RegEdx, 16) & 0xF;
+ switch (States) {
+ case C7s_LONG_LATENCY_SUPPORTED:
+ //
+ // C7 & C7s Long and Short supported
+ //
+ PpmFlags |= (PPM_C7S | C7s_LONG_LATENCY_ENABLE | PPM_C7 | C7_LONG_LATENCY_ENABLE);
+ break;
+ case C7s_SHORT_LATENCY_SUPPORTED:
+ //
+ // C7s Long Latency is not supported.
+ //
+ PpmFlags |= (PPM_C7S | PPM_C7 | C7_LONG_LATENCY_ENABLE);
+ break;
+ case C6_C7_LONG_LATENCY_SUPPORTED:
+ //
+ // C7 Long and Short supported
+ //
+ PpmFlags |= (PPM_C7 | C7_LONG_LATENCY_ENABLE);
+ break;
+ case C6_C7_SHORT_LATENCY_SUPPORTED:
+ //
+ // C7 Long Latency is not supported.
+ //
+ PpmFlags |= PPM_C7;
+ break;
+ }
+
+ States = RShiftU64 (Cpuid05.RegEdx, 20) & 0xF;
+ if (States >= CSTATE_SUPPORTED) {
+ PpmFlags |= PPM_C8;
+ }
+ States = RShiftU64 (Cpuid05.RegEdx, 24) & 0xF;
+ if (States >= CSTATE_SUPPORTED) {
+ PpmFlags |= PPM_C9;
+ }
+ States = RShiftU64 (Cpuid05.RegEdx, 28) & 0xF;
+ if (States >= CSTATE_SUPPORTED) {
+ PpmFlags |= PPM_C10;
+ }
+ ///
+ /// Check TimedMwait is supported and update the flag
+ ///
+ if (AsmReadMsr64 (MSR_PLATFORM_INFO) & B_PLATFORM_INFO_TIMED_MWAIT_SUPPORTED) {
+ PpmFlags |= PPM_TIMED_MWAIT;
+ }
+ if (PpmFlags & (PPM_C8 |PPM_C9 | PPM_C10)) {
+ PpmFlags |= PPM_CD;
+ }
+ ///
+ /// Check if turbo mode is supported and update the flag
+ ///
+ Ia32MiscEnable.Qword = AsmReadMsr64 (MSR_IA32_MISC_ENABLE);
+ if (((Cpuid06.RegEax & B_CPUID_POWER_MANAGEMENT_EAX_TURBO) == 0) &&
+ ((Ia32MiscEnable.Qword & B_MSR_IA32_MISC_DISABLE_TURBO) == 0)
+ ) {
+ ///
+ /// Turbo Mode is not available in this physical processor package.
+ /// BIOS should not attempt to enable Turbo Mode via IA32_MISC_ENABLE MSR.
+ /// BIOS should show Turbo Mode as Disabled and Not Configurable.
+ ///
+ } else if ((Cpuid06.RegEax & B_CPUID_POWER_MANAGEMENT_EAX_TURBO) == 0) {
+ ///
+ /// Turbo Mode is available but globally disabled for the all logical
+ /// processors in this processor package.
+ /// BIOS can enable Turbo Mode by IA32_MISC_ENABLE MSR 1A0h bit [38] = 0.
+ ///
+ PpmFlags |= PPM_TURBO;
+ } else if ((Cpuid06.RegEax & B_CPUID_POWER_MANAGEMENT_EAX_TURBO) == B_CPUID_POWER_MANAGEMENT_EAX_TURBO) {
+ ///
+ /// Turbo Mode is factory-configured as available and enabled for all logical processors in this processor package.
+ /// This case handles the cases where turbo mode is enabled before PPM gets chance to enable it
+ ///
+ PpmFlags |= PPM_TURBO;
+ }
+ ///
+ /// Restore the CPUID limit setting.
+ ///
+ if (CpuidLimitingEnabled) {
+ Ia32MiscEnable.Qword = AsmReadMsr64 (MSR_IA32_MISC_ENABLE);
+ Ia32MiscEnable.Qword |= B_MSR_IA32_MISC_ENABLE_CPUID_MAX;
+ AsmWriteMsr64 (MSR_IA32_MISC_ENABLE, Ia32MiscEnable.Qword);
+ }
+ PpmFlags |= PPM_TSTATES; ///< Set the T-states flag
+ ///
+ /// Determine if Fine grained clock modulation contol is supported
+ ///
+ if (Cpuid06.RegEax & B_CPUID_POWER_MANAGEMENT_EAX_FINE_GRAINED_CLOCK_MODULATION) {
+ PpmFlags |= PPM_TSTATE_FINE_GRAINED;
+ }
+ PpmFlags |= PPM_EEPST; ///< Energy Efficient P-state feature is supported
+ mPpmGlobalNvsAreaProtocol->Area->PpmFlags = PpmFlags; ///< Update the PPM NVS area PPM flags
+
+ return;
+}
+
+/**
+ Set the PPM flags based on current user configuration
+**/
+VOID
+SetUserConfigurationPpmFlags (
+ VOID
+ )
+{
+ UINT32 UserPpmFlag;
+ //
+ // In advance to clear following PPM flags which are related with policies that user can enabled/disabled.
+ //
+ UserPpmFlag = (UINT32)~(PPM_EIST | PPM_C1 | PPM_C1E | PPM_C3 | PPM_C6 | C6_LONG_LATENCY_ENABLE |
+ PPM_C7S | PPM_C7 | C7_LONG_LATENCY_ENABLE | C7s_LONG_LATENCY_ENABLE | PPM_CD |
+ PPM_C8 | PPM_C9 | PPM_C10 | PPM_TM | PPM_TURBO | PPM_TSTATES | PPM_TSTATE_FINE_GRAINED |
+ PPM_EEPST | PPM_TIMED_MWAIT);
+ ///
+ /// Configure flag based on user selections
+ ///
+ if (mCpuPmConfig->pFunctionEnables->Eist) {
+ UserPpmFlag |= PPM_EIST;
+ }
+ if (mCpuPmConfig->pFunctionEnables->Cx) {
+ UserPpmFlag |= PPM_C1;
+ if (mCpuPmConfig->pFunctionEnables->C1e) {
+ UserPpmFlag |= PPM_C1E;
+ }
+ if (mCpuPmConfig->pFunctionEnables->C3) {
+ UserPpmFlag |= PPM_C3;
+ }
+ if (mCpuPmConfig->pFunctionEnables->C6) {
+ UserPpmFlag |= PPM_C6;
+ }
+ if (mCpuPmConfig->pFunctionEnables->LongLatencyC6) {
+ UserPpmFlag |= C6_LONG_LATENCY_ENABLE;
+ }
+ switch (mCpuPmConfig->pFunctionEnables->DeepCState) {
+ case DeepC7S:
+ UserPpmFlag |= PPM_C7S;
+ case DeepC7:
+ UserPpmFlag |= PPM_C7;
+ break;
+ }
+ if (mCpuPmConfig->pFunctionEnables->LongLatencyC7) {
+ UserPpmFlag |= (C7_LONG_LATENCY_ENABLE | C7s_LONG_LATENCY_ENABLE);
+ }
+ if (mCpuPmConfig->pFunctionEnables->C8) {
+ UserPpmFlag |= PPM_C8;
+ }
+ if (mCpuPmConfig->pFunctionEnables->C9) {
+ UserPpmFlag |= PPM_C9;
+ }
+ if (mCpuPmConfig->pFunctionEnables->C10) {
+ UserPpmFlag |= PPM_C10;
+ }
+ if (UserPpmFlag & (PPM_C8 |PPM_C9 | PPM_C10)) {
+ UserPpmFlag |= PPM_CD;
+ }
+ }
+ if (mCpuPmConfig->ThermalFuncEnables->ThermalMonitor) {
+ UserPpmFlag |= PPM_TM;
+ }
+ if (mCpuPmConfig->pFunctionEnables->TurboMode) {
+ UserPpmFlag |= PPM_TURBO;
+ }
+ if (mCpuPmConfig->ThermalFuncEnables->TStates) {
+ UserPpmFlag |= (PPM_TSTATES | PPM_TSTATE_FINE_GRAINED);
+ }
+ if (mCpuPmConfig->pFunctionEnables->EnergyEfficientPState) {
+ UserPpmFlag |= PPM_EEPST;
+ }
+ if (mCpuPmConfig->pFunctionEnables->TimedMwait) {
+ UserPpmFlag |= PPM_TIMED_MWAIT;
+ }
+ ///
+ /// Modify PpmFlags based on user selections
+ ///
+ mPpmGlobalNvsAreaProtocol->Area->PpmFlags &= UserPpmFlag;
+}
+
+/**
+ Initialize the processor power management based on hardware capabilities
+ and user configuration settings.
+
+ @retval EFI_SUCCESS - on success
+ @retval Appropiate failure code on error
+**/
+EFI_STATUS
+InitializePpm (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS CtdpSupport;
+
+ Status = EFI_SUCCESS;
+ CtdpSupport = EFI_UNSUPPORTED;
+
+ ///
+ /// Initialize Config TDP
+ ///
+ CtdpSupport = InitializeConfigurableTdp (mCpuPmConfig);
+
+ ///
+ /// Initialize P states
+ ///
+ InitializePStates();
+
+ ///
+ /// Initialize C State(IdleStates)
+ ///
+ InitializeCState(mCpuPmConfig);
+
+ //
+ // Patch P state table (Fvid table) with ctdp settings.
+ //
+ CtdpPatchFvidTable (mFvidPointer);
+
+ Status = InitializePpmAcpiTable ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ///
+ /// Initialize thermal features
+ ///
+ InitThermal (mCpuPmConfig);
+
+ ///
+ /// Initialise Miscellaneous features
+ ///
+ InitMiscFeatures(CtdpSupport);
+
+ ///
+ /// Complete with Ppmpost initialization
+ ///
+ PpmPostInit ();
+
+ return Status;
+}
+
+
+/**
+ This is a debug function to print PPM Policy
+**/
+VOID
+DumpCpuPmConfig (
+ VOID
+ )
+{
+#ifdef EFI_DEBUG
+ UINT32 Index;
+ DEBUG ((EFI_D_INFO, "\n\n------------------------ PowerMangement Policy dump Begin -----------------\n\n"));
+ DEBUG ((EFI_D_INFO, " S3RestoreMsrSwSmiNumber : %x\n", mCpuPmConfig->S3RestoreMsrSwSmiNumber));
+ DEBUG ((EFI_D_INFO, "\n Ppm Lock Enables... \n"));
+ DEBUG ((EFI_D_INFO, " PmgCstCfgCtrlLock : %x\n", mCpuPmConfig->pPpmLockEnables->PmgCstCfgCtrlLock));
+ DEBUG ((EFI_D_INFO, " ProcHotLock : %x\n", mCpuPmConfig->pPpmLockEnables->ProcHotLock));
+ DEBUG ((EFI_D_INFO, "\n FunctionEnables... \n"));
+ DEBUG ((EFI_D_INFO, " Eist : %x\n", mCpuPmConfig->pFunctionEnables->Eist));
+ DEBUG ((EFI_D_INFO, " Cx : %x\n", mCpuPmConfig->pFunctionEnables->Cx));
+ DEBUG ((EFI_D_INFO, " C1e : %x\n", mCpuPmConfig->pFunctionEnables->C1e));
+ DEBUG ((EFI_D_INFO, " C3 : %x\n", mCpuPmConfig->pFunctionEnables->C3));
+ DEBUG ((EFI_D_INFO, " C6 : %x\n", mCpuPmConfig->pFunctionEnables->C6));
+ DEBUG ((EFI_D_INFO, " C6 Long Latency: %x\n", mCpuPmConfig->pFunctionEnables->LongLatencyC6));
+ DEBUG ((EFI_D_INFO, " DeepCState : %x\n", mCpuPmConfig->pFunctionEnables->DeepCState));
+ DEBUG ((EFI_D_INFO, " C7 Long Latency : %x\n", mCpuPmConfig->pFunctionEnables->LongLatencyC7));
+ DEBUG ((EFI_D_INFO, " C1Autodemotion : %x\n", mCpuPmConfig->pFunctionEnables->C1AutoDemotion));
+ DEBUG ((EFI_D_INFO, " C3AutoDemotion : %x\n", mCpuPmConfig->pFunctionEnables->C3AutoDemotion));
+ DEBUG ((EFI_D_INFO, " C1Undemotion : %x\n", mCpuPmConfig->pFunctionEnables->C1UnDemotion));
+ DEBUG ((EFI_D_INFO, " C3UnDemotion : %x\n", mCpuPmConfig->pFunctionEnables->C3UnDemotion));
+ DEBUG ((EFI_D_INFO, " PkgCstateUndemotion : %x\n", mCpuPmConfig->pFunctionEnables->PkgCStateUnDemotion));
+ DEBUG ((EFI_D_INFO, " PkgCState Demotion : %x\n", mCpuPmConfig->pFunctionEnables->PkgCStateDemotion));
+ DEBUG ((EFI_D_INFO, " CStatePreWake : %x\n", mCpuPmConfig->pFunctionEnables->CStatePreWake));
+ DEBUG ((EFI_D_INFO, " TurboMode : %x\n", mCpuPmConfig->pFunctionEnables->TurboMode));
+ DEBUG ((EFI_D_INFO, " PowerLimit2 : %x\n", mCpuPmConfig->pFunctionEnables->PowerLimit2));
+ DEBUG ((EFI_D_INFO, " EnergyEfficientPState : %x\n", mCpuPmConfig->pFunctionEnables->EnergyEfficientPState));
+ DEBUG ((EFI_D_INFO, " LakeTiny Support : %x\n", mCpuPmConfig->pFunctionEnables->LakeTiny));
+ DEBUG ((EFI_D_INFO, " PkgCStateLimit : %x\n", mCpuPmConfig->PkgCStateLimit));
+ DEBUG ((EFI_D_INFO, " TimedMwait : %x\n", mCpuPmConfig->pFunctionEnables->TimedMwait));
+ DEBUG ((EFI_D_INFO, " CstateLatencyControl0TimeUnit : %x\n", mCpuPmConfig->CstateLatencyControl0TimeUnit));
+ DEBUG ((EFI_D_INFO, " CstateLatencyControl1TimeUnit : %x\n", mCpuPmConfig->CstateLatencyControl1TimeUnit));
+ DEBUG ((EFI_D_INFO, " CstateLatencyControl2TimeUnit : %x\n", mCpuPmConfig->CstateLatencyControl2TimeUnit));
+ DEBUG ((EFI_D_INFO, " CstateLatencyControl3TimeUnit : %x\n", mCpuPmConfig->CstateLatencyControl3TimeUnit));
+ DEBUG ((EFI_D_INFO, " CstateLatencyControl4TimeUnit : %x\n", mCpuPmConfig->CstateLatencyControl4TimeUnit));
+ DEBUG ((EFI_D_INFO, " CstateLatencyControl5TimeUnit : %x\n", mCpuPmConfig->CstateLatencyControl5TimeUnit));
+ DEBUG ((EFI_D_INFO, " CstateLatencyControl0Irtl : %x\n", mCpuPmConfig->CstateLatencyControl0Irtl));
+ DEBUG ((EFI_D_INFO, " CstateLatencyControl1Irtl : %x\n", mCpuPmConfig->CstateLatencyControl1Irtl));
+ DEBUG ((EFI_D_INFO, " CstateLatencyControl2Irtl : %x\n", mCpuPmConfig->CstateLatencyControl2Irtl));
+ DEBUG ((EFI_D_INFO, " RfiFreqTunningOffsetIsNegative : %x\n", mCpuPmConfig->RfiFreqTunningOffsetIsNegative));
+ DEBUG ((EFI_D_INFO, " RfiFreqTunningOffset : %x\n", mCpuPmConfig->RfiFreqTunningOffset));
+ DEBUG ((EFI_D_INFO, "\n Turbo settings... \n"));
+ DEBUG ((EFI_D_INFO, " PowerLimit1 : %x\n", mCpuPmConfig->pTurboSettings->PowerLimit1));
+ DEBUG ((EFI_D_INFO, " PowerLimit1Time : %x\n", mCpuPmConfig->pTurboSettings->PowerLimit1Time));
+ DEBUG ((EFI_D_INFO, " PowerLimit2 : %x\n", mCpuPmConfig->pTurboSettings->PowerLimit2));
+ DEBUG ((EFI_D_INFO, " PowerLimit3 : %x\n", mCpuPmConfig->pTurboSettings->PowerLimit3));
+ DEBUG ((EFI_D_INFO, " PowerLimit3Time : %x\n", mCpuPmConfig->pTurboSettings->PowerLimit3Time));
+ DEBUG ((EFI_D_INFO, " PowerLimit3DutyCycle : %x\n", mCpuPmConfig->pTurboSettings->PowerLimit3DutyCycle));
+ DEBUG ((EFI_D_INFO, " PowerLimit3Lock : %x\n", mCpuPmConfig->pTurboSettings->PowerLimit3Lock));
+ DEBUG ((EFI_D_INFO, " TurboPowerLimitLock : %x\n", mCpuPmConfig->pTurboSettings->TurboPowerLimitLock));
+ DEBUG ((EFI_D_INFO, " ConfigTdpLevel : %x\n", mCpuPmConfig->pTurboSettings->ConfigTdpLevel));
+ DEBUG ((EFI_D_INFO, " ConfigTdpLock : %x\n", mCpuPmConfig->pTurboSettings->ConfigTdpLock));
+ DEBUG ((EFI_D_INFO, " ConfigTdpCustom : %x\n", mCpuPmConfig->pCustomCtdpSettings->ConfigTdpCustom));
+ if (mCpuPmConfig->pCustomCtdpSettings->ConfigTdpCustom) {
+ DEBUG ((EFI_D_INFO, " CustomTdpCount : %d\n", mCpuPmConfig->pCustomCtdpSettings->CustomTdpCount));
+ DEBUG ((EFI_D_INFO, " CustomBootModeIndex : %d\n", mCpuPmConfig->pCustomCtdpSettings->CustomBootModeIndex));
+ for (Index = 0; Index < MAX_CUSTOM_CTDP_ENTRIES; Index++) {
+ DEBUG (
+ (EFI_D_INFO,
+ " CustomConfigTdpTable[%d] CustomPowerLimit1 : 0x%x\n",
+ Index,mCpuPmConfig->pCustomCtdpSettings->CustomConfigTdpTable[Index].CustomPowerLimit1)
+ );
+ DEBUG (
+ (EFI_D_INFO,
+ " CustomConfigTdpTable[%d] CustomPowerLimit2 : 0x%x\n",
+ Index,mCpuPmConfig->pCustomCtdpSettings->CustomConfigTdpTable[Index].CustomPowerLimit2)
+ );
+ DEBUG (
+ (EFI_D_INFO,
+ " CustomConfigTdpTable[%d] CustomPowerLimit1Time : %d\n",
+ Index,mCpuPmConfig->pCustomCtdpSettings->CustomConfigTdpTable[Index].CustomPowerLimit1Time)
+ );
+ DEBUG (
+ (EFI_D_INFO,
+ " CustomConfigTdpTable[%d] CustomTurboActivationRatio : %d\n",
+ Index,mCpuPmConfig->pCustomCtdpSettings->CustomConfigTdpTable[Index].CustomTurboActivationRatio)
+ );
+ DEBUG (
+ (EFI_D_INFO,
+ " ConfigTdpTable[%d] CustomConfigTdpControl : %d\n",
+ Index,mCpuPmConfig->pCustomCtdpSettings->CustomConfigTdpTable[Index].CustomConfigTdpControl)
+ );
+ }
+ }
+ DEBUG ((EFI_D_INFO, "\n CustomRatioTable... \n"));
+ DEBUG ((EFI_D_INFO, " VidNumber : %x\n", mCpuPmConfig->pCustomRatioTable->NumberOfEntries));
+ DEBUG ((EFI_D_INFO, " VidCpuid : %x\n", mCpuPmConfig->pCustomRatioTable->Cpuid));
+ DEBUG ((EFI_D_INFO, " VidMaxRatio : %x\n", mCpuPmConfig->pCustomRatioTable->MaxRatio));
+ for (Index = 0; Index < MAX_CUSTOM_RATIO_TABLE_ENTRIES; Index++) {
+ DEBUG ((EFI_D_INFO, " StateRatio[%d] : %x\n", Index, mCpuPmConfig->pCustomRatioTable->StateRatio[Index]));
+ }
+ DEBUG ((EFI_D_INFO, "\n XeConfig... \n"));
+ DEBUG ((EFI_D_INFO, " Xe : %x\n", mCpuPmConfig->pFunctionEnables->Xe));
+ for (Index = 0; Index < 4; Index++) {
+ DEBUG ((EFI_D_INFO, " RatioLimit[%d] : %x\n", Index, mCpuPmConfig->pRatioLimit[Index]));
+ }
+ DEBUG ((EFI_D_INFO, " BiProcHot : %x\n", mCpuPmConfig->ThermalFuncEnables->BiProcHot));
+ DEBUG ((EFI_D_INFO, " DisableProcHotOut : %x\n", mCpuPmConfig->ThermalFuncEnables->DisableProcHotOut));
+ DEBUG ((EFI_D_INFO, " DisableVRThermalAlert : %x\n", mCpuPmConfig->ThermalFuncEnables->DisableVRThermalAlert));
+ DEBUG ((EFI_D_INFO, " ProcHotResponce : %x\n", mCpuPmConfig->ThermalFuncEnables->ProcHotResponce));
+ DEBUG ((EFI_D_INFO, " TStates : %x\n", mCpuPmConfig->ThermalFuncEnables->TStates));
+ DEBUG ((EFI_D_INFO, " AutoThermalReporting : %x\n", mCpuPmConfig->ThermalFuncEnables->AutoThermalReporting));
+ DEBUG ((EFI_D_INFO, " ThermalMonitor : %x\n", mCpuPmConfig->ThermalFuncEnables->ThermalMonitor));
+ DEBUG ((EFI_D_INFO, "\n\n------------------------ PowerMangement Policy dump End -------------------\n\n"));
+#endif
+}
diff --git a/ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtInit.h b/ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtInit.h
new file mode 100644
index 0000000..9e138c6
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/Dxe/PowerMgmtInit.h
@@ -0,0 +1,127 @@
+/** @file
+ This header file contains power management definitions specific to
+ Haswell processors.
+
+@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 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
+**/
+#ifndef _POWER_MANAGEMENT_H_
+#define _POWER_MANAGEMENT_H_
+
+#include "PowerMgmtCommon.h"
+
+//
+// Function prototypes
+//
+/**
+ Initialize the power management support.
+ This function will do boot time configuration:
+ Install into SMRAM/SMM
+ Detect HW capabilities and SW configuration
+ Initialize HW and software state (primarily MSR and ACPI tables)
+ Install SMI handlers for runtime interfacess
+
+ @param[in] ImageHandle Pointer to the loaded image protocol for this driver
+ @param[in] SystemTable Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS The driver installed/initialized correctly.
+ @retval Driver will ASSERT in debug builds on error. PPM functionality is considered critical for mobile systems.
+**/
+EFI_STATUS
+InitializePowerManagement (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Initializes the CPU power management global variable.
+ This must be called prior to any of the functions being used.
+
+ @retval EFI_SUCCESS Library was initialized successfully
+ @retval EFI_DEVICE_ERROR If CPU is not supported by this library
+**/
+VOID
+InitializePowerManagementGlobalVariables (
+ VOID
+ );
+
+/**
+ Create a custom FVID table based on setup options.
+ Caller is responsible for providing a large enough table.
+
+ @param[in] FvidPointer Table to update, must be initialized.
+**/
+VOID
+CreateCustomFvidTable (
+ IN OUT FVID_TABLE *FvidPointer
+ );
+
+/**
+ Sets up the PPM flags based upon capabilities
+
+ @param[in] This - None
+
+ @retval EFI_STATUS
+**/
+VOID
+SetPpmFlags (
+ VOID
+ );
+
+/**
+ Set the PPM flags based on current user configuration obtained from PPM platform policy protocol
+
+ @param[in] PpmFlagsMask Mask of feature options to be enabled as specified by the policy
+**/
+VOID
+SetUserConfigurationPpmFlags (
+ );
+
+/**
+ Initialize the platform power management based on hardware capabilities
+ and user configuration settings.
+
+ This includes creating FVID table, updating ACPI tables,
+ and updating processor and chipset hardware configuration.
+
+ This should be called prior to any Px, Cx, Tx activity.
+
+ @retval EFI_SUCCESS - on success
+ @retval Appropiate failure code on error
+**/
+EFI_STATUS
+InitializePpm (
+ VOID
+ );
+
+/**
+ This is a debug function to print PPM Policy
+**/
+VOID
+DumpCpuPmConfig (
+ VOID
+ );
+
+/**
+ This is a debug function to print PPM Global NVS area
+**/
+VOID
+DumpPPMGlobalNvs (
+ VOID
+ );
+
+#endif
diff --git a/ReferenceCode/Haswell/PowerManagement/Dxe/Thermal.c b/ReferenceCode/Haswell/PowerManagement/Dxe/Thermal.c
new file mode 100644
index 0000000..d60635e
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/Dxe/Thermal.c
@@ -0,0 +1,301 @@
+/** @file
+ This library contains power management configuration functions for
+ Haswell processors.
+
+ Acronyms:
+ PPM - Processor Power Management
+ TM - Thermal Monitor
+ IST - Intel(R) Speedstep technology
+ HT - Hyper-Threading Technology
+
+@copyright
+ Copyright (c) 2012 - 2014 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
+
+**/
+#include "PowerMgmtCommon.h"
+
+/**
+ This will perform general thermal initialization other then TM1, TM2, or
+ PROCHOT# on all logical processors.
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+ @param[in] PpmGlobalNvsAreaProtocol Pointer to PPM Global Nvs area
+
+ @retval EFI_SUCCESS General thermal initialization completed successfully
+**/
+VOID
+InitThermal (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ )
+{
+ MSR_REGISTER TempMsr;
+ UINT8 MaxRefTemp;
+ CPU_FAMILY CpuFamilyId;
+ CPU_STEPPING CpuStepping;
+ UINT8 TccActivationOffsetMask;
+
+ ///
+ /// Run thermal code on all logical processors.
+ ///
+ RunOnAllLogicalProcessors (ApSafeInitThermal, CpuPmConfig);
+ ///
+ /// Automatic Thermal Reporting for Thermal Management
+ ///
+ if (CpuPmConfig->ThermalFuncEnables->AutoThermalReporting) {
+ ///
+ /// Thermal Reporting for Critical trip
+ /// MSR 1A2 bits 23:16 define the temperature that this specific processor can
+ /// function upto. It is recommended that this value + 5 be used as default Critical trip point
+ /// _CRT.
+ ///
+ TempMsr.Qword = AsmReadMsr64 (MSR_TEMPERATURE_TARGET);
+ TempMsr.Qword &= B_MSR_TEMPERATURE_TARGET_TCC_ACTIVATION_TEMPERATURE_MASK;
+ MaxRefTemp = (UINT8) RShiftU64 (TempMsr.Qword, N_MSR_TEMPERATURE_TARGET_TCC_ACTIVATION_TEMPERATURE_OFFSET);
+ mPpmGlobalNvsAreaProtocol->Area->AutoCriticalTripPoint = MaxRefTemp + 5;
+ ///
+ /// Thermal Reporting for Active Thermal Management
+ /// It is recommended that the processor specific value in MSR 1A2 bits 15:8
+ /// be used as the highest Active trip point i.e. _AC0.
+ ///
+ TempMsr.Qword = AsmReadMsr64 (MSR_TEMPERATURE_TARGET);
+ TempMsr.Qword &= B_MSR_TEMPERATURE_TARGET_FAN_TEMP_TARGET_OFFSET;
+ mPpmGlobalNvsAreaProtocol->Area->AutoActiveTripPoint = MaxRefTemp - (UINT8) RShiftU64 (
+ TempMsr.Qword,
+ N_MSR_TEMPERATURE_TARGET_FAN_TEMP_TARGET_OFFSET
+ );
+
+ ///
+ /// Tcc activation offset in temperature target MSR changes from 4 bits [27:24] to 6 bits [29:24] on ULT C step onwards
+ ///
+ CpuFamilyId = mPpmGlobalNvsAreaProtocol->Area->Cpuid & CPUID_FULL_FAMILY_MODEL;
+ CpuStepping = mPpmGlobalNvsAreaProtocol->Area->Cpuid & CPUID_FULL_STEPPING;
+ if ((CpuFamilyId == EnumCpuHswUlt) && (CpuStepping >= EnumHswUltC0)) {
+ TccActivationOffsetMask = 0x3F;
+ } else {
+ TccActivationOffsetMask = 0xF;
+ }
+
+ ///
+ /// Thermal Reporting for Passive Thermal Management
+ /// On all turbo enabled systems, it is recommended that the ACPI _PSV point be
+ /// set to a temperature above the Active cooling temperature and Tcc activation
+ /// temperature.
+ /// If platform embedded controller will issue PECI commands to reduce power as a
+ /// passive thermal action, then it is recommended to use the package's max temperature
+ /// for passive thermal control.
+ ///
+ TempMsr.Qword = AsmReadMsr64 (MSR_TEMPERATURE_TARGET);
+ TempMsr.Qword &= (TccActivationOffsetMask << N_MSR_TEMPERATURE_TARGET_TCC_OFFSET_LIMIT);
+ mPpmGlobalNvsAreaProtocol->Area->AutoPassiveTripPoint = mPpmGlobalNvsAreaProtocol->Area->AutoCriticalTripPoint+3;
+ }
+
+ EnableProcHot ();
+ return;
+}
+
+/**
+ This will perform enable thermal initialization. TM1, TM2 and adaptive thermal
+ throttling are enabled/disabled together.
+
+ This function must be MP safe.
+
+ @param[in] Buffer Pointer to the function parameters passed in.
+
+ @retval EFI_SUCCESS General thermal initialization completed successfully
+**/
+VOID
+EFIAPI
+ApSafeInitThermal (
+ IN OUT VOID *Buffer
+ )
+{
+ MSR_REGISTER TempMsr;
+ POWER_MGMT_CONFIG *This;
+
+ ///
+ /// Extract parameters from the buffer
+ ///
+ This = (POWER_MGMT_CONFIG *) Buffer;
+ ///
+ /// Configure Adaptive thermal monitor. IA32_MISC_ENABLE[3]
+ /// HSW BWG (1A0h)IA32_MISC_ENABLE - Bit3:Intel Adaptive Thermal Monitor Enable
+ /// System BIOS must always set this bit to be operating within spec.
+ ///
+ TempMsr.Qword = AsmReadMsr64 (MSR_IA32_MISC_ENABLE);
+ TempMsr.Dwords.Low |= B_MSR_IA32_MISC_ENABLE_TME;
+ if (This->ThermalFuncEnables->ThermalMonitor == 0) {
+ TempMsr.Dwords.Low &= ~B_MSR_IA32_MISC_ENABLE_TME;
+ }
+ AsmWriteMsr64 (MSR_IA32_MISC_ENABLE, TempMsr.Qword);
+ ///
+ /// Set the Lock TM interrupt bit so that thermal interrupts are routed to all the cores
+ ///
+ TempMsr.Qword = AsmReadMsr64 (MSR_MISC_PWR_MGMT);
+ TempMsr.Qword |= B_MSR_MISC_PWR_MGMT_LTMI;
+ AsmWriteMsr64 (MSR_MISC_PWR_MGMT, TempMsr.Qword);
+ ///
+ /// Enable Critical Temperature Interrupt
+ ///
+ TempMsr.Qword = AsmReadMsr64 (IA32_THERM_INTERRUPT);
+ TempMsr.Qword |= B_IA32_THERM_INTERRUPT_VIE;
+ AsmWriteMsr64 (IA32_THERM_INTERRUPT, TempMsr.Qword);
+
+ return;
+}
+
+/**
+ Enables the bi-directional PROCHOT# signal.
+
+ @retval EFI_SUCCESS PROCHOT# configured successfully
+**/
+EFI_STATUS
+EnableProcHot (
+ VOID
+ )
+{
+ MSR_REGISTER PowerCtl;
+
+ ///
+ /// Enable PROCHOT# in the CPU MSR if TM is enabled,
+ /// else disable it.
+ ///
+ PowerCtl.Qword = AsmReadMsr64 (MSR_POWER_CTL);
+ if (mPpmGlobalNvsAreaProtocol->Area->PpmFlags & (PPM_TM)) {
+ PowerCtl.Qword &= ~B_MSR_POWER_CTL_DISABLE_VR_THERMAL_ALERT;
+ if ((mCpuPmConfig->ThermalFuncEnables->DisableVRThermalAlert == 1)) {
+ DEBUG ((EFI_D_INFO, "VR Thermal Alert is disabled\n"));
+ PowerCtl.Qword |= B_MSR_POWER_CTL_DISABLE_VR_THERMAL_ALERT;
+ }
+ ///
+ /// Check PROCHOT Lock,skip programming the below as it will lock bits 0, 21, 22
+ ///
+ if (!(PowerCtl.Qword & B_MSR_POWER_CTL_PROC_HOT_LOCK)) {
+ PowerCtl.Qword &= ~B_MSR_POWER_CTL_BROCHOT;
+ if (mCpuPmConfig->ThermalFuncEnables->BiProcHot) {
+ PowerCtl.Qword |= B_MSR_POWER_CTL_BROCHOT;
+ ///
+ /// Initialize PROCHOT# OUT basing on Bi-directional PROCHOT# setting
+ /// If Bi-directional PROCHOT# is enabled, PROCHOT# OUT can be disabled selectively
+ ///
+ PowerCtl.Qword &= ~B_MSR_POWER_CTL_DISABLE_PHOT_OUT;
+ if ((mCpuPmConfig->ThermalFuncEnables->DisableProcHotOut == 1)) {
+ DEBUG ((EFI_D_INFO, "PROCHOT# OUT is disabled\n"));
+ PowerCtl.Qword |= B_MSR_POWER_CTL_DISABLE_PHOT_OUT;
+ }
+ }
+ PowerCtl.Qword &= ~B_MSR_POWER_CTL_PROC_HOT_RESPONSE;
+ if ((mCpuPmConfig->ThermalFuncEnables->ProcHotResponce == 1)) {
+ DEBUG ((EFI_D_INFO, "PROCHOT# Response is enabled\n"));
+ PowerCtl.Qword |= B_MSR_POWER_CTL_PROC_HOT_RESPONSE;
+ }
+ }
+ AsmWriteMsr64 (MSR_POWER_CTL, PowerCtl.Qword);
+ }
+
+ return EFI_SUCCESS;
+}
+/**
+ This will perform PowerLimit 1 algorithm will be used to control Thermal Throttling features
+
+ @param[in] CpuPmConfig Pointer to policy protocol instance
+**/
+VOID
+InitPl1ThermalControl (
+ IN OUT POWER_MGMT_CONFIG *CpuPmConfig
+ )
+{
+ UINT32 MailBoxStatus;
+ PL1_THERMAL_CONTROL WritePL1ThermalControl;
+ PL1_THERMAL_CONTROL ReadPL1ThermalControl;
+ CPU_FAMILY CpuFamilyId;
+ CPU_STEPPING CpuSteppingId;
+ MSR_REGISTER PakagePowerLimitMsr;
+ UINTN PciD0F0RegBase;
+ UINTN MchBar;
+
+ MailBoxStatus = 0;
+ ReadPL1ThermalControl.Uint32 = 0;
+ WritePL1ThermalControl.Uint32 = 0;
+
+ CpuFamilyId = mPpmGlobalNvsAreaProtocol->Area->Cpuid & CPUID_FULL_FAMILY_MODEL;
+ CpuSteppingId = mPpmGlobalNvsAreaProtocol->Area->Cpuid & CPUID_FULL_STEPPING;
+
+
+ if (((CpuFamilyId == EnumCpuHswUlt) && (CpuSteppingId >= EnumHswUltC0))
+ || ((CpuFamilyId == EnumCpuHsw) && (CpuSteppingId >= EnumHswC0))
+ || ((CpuFamilyId == EnumCpuCrw) && (CpuSteppingId >= EnumCrwC0))
+ ) {
+ ///
+ /// If User selects Auto,Enable by default on ULX and disable on orther processor
+ ///
+ if (CpuPmConfig->ThermalFuncEnables->Pl1ThermalControl == 1) { // 0 = disable, 1 = enable (manual), 2 = auto
+ WritePL1ThermalControl.Bits.Disable = 0;
+ } else if (CpuPmConfig->ThermalFuncEnables->Pl1ThermalControl == 2) {
+ if (mPackageTdp < 15 * mProcessorPowerUnit) { // ULX
+ WritePL1ThermalControl.Bits.Disable = 0;
+ } else {
+ WritePL1ThermalControl.Bits.Disable = 1;
+ }
+ } else {
+ WritePL1ThermalControl.Bits.Disable = 1;
+ }
+ if (mCpuPolicyRevision >= 7) {
+ WritePL1ThermalControl.Bits.FloorIA = CpuPmConfig->ThermalFuncEnables->Pl1ThermalControlFloor.FloorIA;
+ WritePL1ThermalControl.Bits.FloorGT = CpuPmConfig->ThermalFuncEnables->Pl1ThermalControlFloor.FloorGT;
+ WritePL1ThermalControl.Bits.FloorPCH = CpuPmConfig->ThermalFuncEnables->Pl1ThermalControlFloor.FloorPCH;
+ }
+
+ MailboxRead(MAILBOX_TYPE_PCODE, READ_PL1_DUTY_CYCLE_CLAMP_ENABLE, (UINT32 *) &ReadPL1ThermalControl, &MailBoxStatus);
+ if (MailBoxStatus != PCODE_MAILBOX_CC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Failure to read PowerLimit1 duty sysle clamp enable. \n"));
+ return;
+ }
+ DEBUG ((EFI_D_INFO, "Current Pl1ThermalControl reading from Mailbox : %d. Requested setting to Mailbox: %d\n", ReadPL1ThermalControl.Uint32, WritePL1ThermalControl.Uint32));
+ ///
+ /// If Mailbox returns differnt from user selection send command to set user selection
+ ///
+ if (ReadPL1ThermalControl.Uint32 != WritePL1ThermalControl.Uint32) {
+ MailboxWrite(MAILBOX_TYPE_PCODE, WRITE_PL1_DUTY_CYCLE_CLAMP_ENABLE, WritePL1ThermalControl.Uint32,&MailBoxStatus);
+ if (MailBoxStatus != PCODE_MAILBOX_CC_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Failure to write PowerLimit1 duty sysle clamp enable. \n"));
+ return;
+ }
+ }
+ MailboxS3Write(WRITE_PL1_DUTY_CYCLE_CLAMP_ENABLE, WritePL1ThermalControl.Uint32);
+
+ ///
+ /// Set PACKAGE_POWER_LIMIT.CRITICAL_POWER_CLAMP_1(bit 16)
+ /// And MMIO_TURBO_POWER_LIMIT.CRITICAL_POWER_CLAMP_1(bit 16)
+ ///
+ PakagePowerLimitMsr.Qword = AsmReadMsr64 (MSR_PACKAGE_POWER_LIMIT);
+ PakagePowerLimitMsr.Dwords.Low |= B_CRITICAL_POWER_CLAMP_ENABLE;
+ AsmWriteMsr64 (MSR_PACKAGE_POWER_LIMIT, PakagePowerLimitMsr.Qword);
+
+ PciD0F0RegBase = MmPciAddress (0, 0, 0, 0, 0);
+ MchBar = MmioRead32 (PciD0F0RegBase + 0x48) &~BIT0;
+ MmioOr32 (MchBar + MMIO_TURBO_POWER_LIMIT, B_CRITICAL_POWER_CLAMP_ENABLE);
+
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINTN) (MchBar + MMIO_TURBO_POWER_LIMIT),
+ 1,
+ (VOID *) (UINTN) (MchBar + MMIO_TURBO_POWER_LIMIT)
+ );
+ }
+ return;
+}
diff --git a/ReferenceCode/Haswell/PowerManagement/Smm/PowerMgmtS3.c b/ReferenceCode/Haswell/PowerManagement/Smm/PowerMgmtS3.c
new file mode 100644
index 0000000..6a26231
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/Smm/PowerMgmtS3.c
@@ -0,0 +1,333 @@
+/** @file
+ This is the SMM driver for saving and restoring the powermanagement related MSRs
+
+@copyright
+ Copyright (c) 2011 - 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 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
+
+**/
+#include "PowerMgmtS3.h"
+#include "PowerMgmtDefinitions.h"
+#include "CpuAccess.h"
+#include "CpuPlatformLib.h"
+
+#include EFI_PROTOCOL_DEPENDENCY (CpuPlatformPolicy)
+#include EFI_PROTOCOL_DEPENDENCY (SmmSwDispatch)
+#include EFI_PROTOCOL_DEPENDENCY (SmmBase)
+
+///
+/// SMM system table pointer
+///
+EFI_SMM_SYSTEM_TABLE *mSmst;
+DXE_CPU_PLATFORM_POLICY_PROTOCOL *mCpuPlatformPolicy;
+///
+/// MSR table for S3 resume
+///
+STATIC EFI_MSR_VALUES mMsrValues[] = {
+ { MSR_IA32_PERF_CTRL, 0, B_IA32_PERF_CTRLP_STATE_TARGET, TRUE },
+ { MSR_PMG_IO_CAPTURE_BASE, 0, 0xFFFFFFFFFFFFFFFF, TRUE },
+ { MSR_PMG_CST_CONFIG, 0, 0xFFFFFFFFFFFFFFFF, TRUE },
+ { MSR_MISC_PWR_MGMT, 0, 0xFFFFFFFFFFFFFFFF, TRUE },
+ { MSR_IA32_MISC_ENABLE, 0, B_CPUID_POWER_MANAGEMENT_EAX_TURBO | B_MSR_IA32_MISC_DISABLE_TURBO | B_MSR_IA32_MISC_ENABLE_MONITOR | B_MSR_IA32_MISC_ENABLE_TME | B_MSR_IA32_MISC_ENABLE_EIST, TRUE },
+ { MSR_POWER_CTL, 0, 0xFFFFFFFFFFFFFFFF, TRUE },
+ { MSR_PACKAGE_POWER_LIMIT, 0, 0xFFFFFFFFFFFFFFFF, TRUE },
+ { MSR_PLATFORM_POWER_LIMIT, 0, 0xFFFFFFFFFFFFFFFF, FALSE },
+ { MSR_C_STATE_LATENCY_CONTROL_0, 0, 0xFFFFFFFFFFFFFFFF, TRUE },
+ { MSR_C_STATE_LATENCY_CONTROL_1, 0, 0xFFFFFFFFFFFFFFFF, TRUE },
+ { MSR_C_STATE_LATENCY_CONTROL_2, 0, 0xFFFFFFFFFFFFFFFF, TRUE },
+ { MSR_C_STATE_LATENCY_CONTROL_3, 0, 0xFFFFFFFFFFFFFFFF, FALSE },
+ { MSR_C_STATE_LATENCY_CONTROL_4, 0, 0xFFFFFFFFFFFFFFFF, FALSE },
+ { MSR_C_STATE_LATENCY_CONTROL_5, 0, 0xFFFFFFFFFFFFFFFF, FALSE },
+ { MSR_FLEX_RATIO, 0, 0xFFFFFFFFFFFFFFFF, TRUE },
+ { MSR_IA32_ENERGY_PERFORMANCE_BIAS, 0, 0xFFFFFFFFFFFFFFFF, TRUE },
+ { MSR_CONFIG_TDP_CONTROL, 0, 0xFFFFFFFFFFFFFFFF, FALSE },
+ { MSR_RFI_TUNNING, 0, 0xFFFFFFFFFFFFFFFF, FALSE },
+ { MSR_TURBO_ACTIVATION_RATIO, 0, 0xFFFFFFFFFFFFFFFF, FALSE },
+ { MSR_DDR_RAPL_LIMIT, 0, 0xFFFFFFFFFFFFFFFF, FALSE },
+ { MSR_TURBO_RATIO_LIMIT, 0, 0xFFFFFFFFFFFFFFFF, TRUE }
+};
+
+/**
+ Save processor MSR runtime settings for S3.
+
+ @retval EFI_SUCCESS Processor MSR setting is saved.
+**/
+STATIC
+EFI_STATUS
+S3SaveMsr (
+ VOID
+ )
+{
+ UINT32 Index;
+ EFI_CPUID_REGISTER Cpuid06 = { 0, 0, 0, 0 };
+ UINT64 MsrValue;
+
+ for (Index = 0; Index < sizeof (mMsrValues) / sizeof (EFI_MSR_VALUES); Index++) {
+ DEBUG ((EFI_D_INFO, " MSR Number: %x\n", mMsrValues[Index].Index));
+ if (mMsrValues[Index].Index == MSR_IA32_ENERGY_PERFORMANCE_BIAS) {
+ ///
+ /// MSR_IA32_ENERGY_PERFORMANCE_BIAS (1B0h) is accessible only if CPUID(6), ECX[3] = 1 to indicate feature availability.
+ ///
+ AsmCpuid (CPUID_FUNCTION_6, &Cpuid06.RegEax, &Cpuid06.RegEbx, &Cpuid06.RegEcx, &Cpuid06.RegEdx);
+ if (!(Cpuid06.RegEcx & B_CPUID_POWER_MANAGEMENT_ECX_ENERGY_EFFICIENT_POLICY_SUPPORT)) {
+ mMsrValues[Index].RestoreFlag = FALSE;
+ continue;
+ }
+ }
+ ///
+ /// Check for HSW specific MSRs
+ ///
+ MsrValue = AsmReadMsr64 (MSR_PLATFORM_INFO);
+ ///
+ ///
+ /// Check PLATFORM_INFO MSR[34:33] > 0 before accessing the MSR_CONFIG_TDP_CONTROL
+ ///
+ if ((mMsrValues[Index].Index == MSR_CONFIG_TDP_CONTROL) &&
+ ((RShiftU64 (MsrValue, N_MSR_PLATFORM_INFO_CONFIG_TDP_NUM_LEVELS_OFFSET) & 0x03))
+ ) {
+ mMsrValues[Index].RestoreFlag = TRUE;
+ }
+ ///
+ /// MSR_TURBO_ACTIVATION_RATIO, MSR_DDR_RAPL_LIMIT, MSR_RFI_TUNNING are supported only on HSW A0 or above.
+ ///
+ if (mMsrValues[Index].Index == MSR_TURBO_ACTIVATION_RATIO) {
+ mMsrValues[Index].RestoreFlag = TRUE;
+ }
+ if (mMsrValues[Index].Index == MSR_DDR_RAPL_LIMIT) {
+ mMsrValues[Index].RestoreFlag = TRUE;
+ }
+ ///
+ /// Check PLATFORM_INFO MSR[25] == 1 before accessing the MSR_RFI_TUNNING
+ ///
+ if (mMsrValues[Index].Index == MSR_RFI_TUNNING) {
+ if ((mCpuPlatformPolicy->PowerMgmtConfig->RfiFreqTunningOffset != AUTO) && (MsrValue & B_FIVR_RFI_TUNING_AVAIL)) {
+ mMsrValues[Index].RestoreFlag = TRUE;
+ }
+ }
+
+ if(GetCpuSku()== EnumCpuUlt) {
+ if ((mMsrValues[Index].Index == MSR_C_STATE_LATENCY_CONTROL_3) ||
+ (mMsrValues[Index].Index == MSR_C_STATE_LATENCY_CONTROL_4)||
+ (mMsrValues[Index].Index == MSR_C_STATE_LATENCY_CONTROL_5)){
+ mMsrValues[Index].RestoreFlag = TRUE;
+ }
+ }
+
+ ///
+ /// PL3 is supported on HSW ULT C0 & HSW C0 and later
+ ///
+ if (mMsrValues[Index].Index == MSR_PLATFORM_POWER_LIMIT) {
+ if (((GetCpuFamily() == EnumCpuHsw) && (GetCpuStepping() >= EnumHswC0))
+ || ((GetCpuFamily() == EnumCpuHswUlt) && (GetCpuStepping() >= EnumHswUltC0))) {
+ mMsrValues[Index].RestoreFlag = TRUE;
+ }
+ }
+
+ if (mMsrValues[Index].RestoreFlag == TRUE) {
+ mMsrValues[Index].Value = AsmReadMsr64 (mMsrValues[Index].Index);
+ DEBUG ((EFI_D_INFO, " MSR Number %x read Done \n", mMsrValues[Index].Index));
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Restore processor MSR runtime settings for S3.
+
+ @param[in] DispatchHandle - The handle of this callback, obtained when registering
+ @param[in] DispatchContex - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT
+
+ @retval EFI_SUCCESS Processor MSR setting is restored.
+**/
+void
+S3RestoreMsr (
+ IN EFI_HANDLE DispatchHandle,
+ IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContex
+ )
+{
+ ///
+ /// Restore MSR's on all logical processors.
+ ///
+ RunOnAllLogicalProcessors (ApSafeRestoreMsr, NULL);
+}
+
+/**
+ Runs the specified procedure on all logical processors, passing in the
+ parameter buffer to the procedure.
+
+ @param[in] Procedure The function to be run.
+ @param[in] Buffer Pointer to a parameter buffer.
+
+ @retval EFI_SUCCESS
+**/
+STATIC
+EFI_STATUS
+RunOnAllLogicalProcessors (
+ IN OUT EFI_AP_PROCEDURE Procedure,
+ IN OUT VOID *Buffer
+ )
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ ///
+ /// Run the procedure on all logical processors.
+ ///
+ (*Procedure)(Buffer);
+ for (Index = 1; Index < mSmst->NumberOfCpus; Index++) {
+ Status = EFI_NOT_READY;
+ while (Status != EFI_SUCCESS) {
+ Status = mSmst->SmmStartupThisAp (Procedure, Index, Buffer);
+ if (Status != EFI_SUCCESS) {
+ ///
+ /// SmmStartupThisAp might return failure if AP is busy executing some other code. Let's wait for sometime and try again.
+ ///
+ PchPmTimerStall (PPM_WAIT_PERIOD);
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function will restore MSR settings.
+
+ This function must be MP safe.
+
+ @param[in] Buffer Unused
+
+ @retval EFI_SUCCESS MSR restored
+**/
+VOID
+EFIAPI
+ApSafeRestoreMsr (
+ IN OUT VOID *Buffer
+ )
+{
+ UINT32 Index;
+ UINT64 MsrValue;
+
+ for (Index = 0; Index < sizeof (mMsrValues) / sizeof (EFI_MSR_VALUES); Index++) {
+ ///
+ /// Check RestoreFlag and skip restoring the MSR if it is set to FALSE
+ ///
+ if (mMsrValues[Index].RestoreFlag == FALSE) {
+ DEBUG ((EFI_D_INFO, "Skipping MSR : %x as RestoreFalg is set to FALSE \n", mMsrValues[Index].Index));
+ continue;
+ }
+ ///
+ /// Check for Lock bits before programming
+ ///
+ MsrValue = AsmReadMsr64 (mMsrValues[Index].Index);
+ if ((mMsrValues[Index].Index == MSR_CONFIG_TDP_CONTROL) && (MsrValue & CONFIG_TDP_CONTROL_LOCK)) {
+ continue;
+ }
+
+ if ((mMsrValues[Index].Index == MSR_TURBO_ACTIVATION_RATIO) && (MsrValue & MSR_TURBO_ACTIVATION_RATIO_LOCK)) {
+ continue;
+ }
+
+ if ((mMsrValues[Index].Index == MSR_PACKAGE_POWER_LIMIT) && (MsrValue & B_POWER_LIMIT_LOCK)) {
+ continue;
+ }
+
+ if ((mMsrValues[Index].Index == MSR_PLATFORM_POWER_LIMIT) && (MsrValue & B_POWER_LIMIT_LOCK)) {
+ continue;
+ }
+
+ if ((mMsrValues[Index].Index == MSR_DDR_RAPL_LIMIT) && (MsrValue & B_POWER_LIMIT_LOCK)) {
+ continue;
+ }
+
+ MsrValue = AsmReadMsr64 (mMsrValues[Index].Index);
+ MsrValue &= ~mMsrValues[Index].BitMask;
+ MsrValue |= (mMsrValues[Index].Value & mMsrValues[Index].BitMask);
+ AsmWriteMsr64 (mMsrValues[Index].Index, MsrValue);
+ }
+
+ return;
+}
+
+/**
+ Initialize the S3 power management Handler.
+
+ @param[in] ImageHandle - Pointer to the loaded image protocol for this driver
+ @param[in] SystemTable - Pointer to the EFI System Table
+
+ @retval EFI_SUCCESS The driver installes/initialized correctly.
+**/
+EFI_STATUS
+PowerMgmtS3SmmEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+
+ EFI_STATUS Status;
+ EFI_SMM_SW_DISPATCH_CONTEXT SwContext;
+ EFI_SMM_SW_DISPATCH_PROTOCOL *SwDispatch;
+ EFI_HANDLE SwHandle;
+ EFI_SMM_BASE_PROTOCOL *SmmBase;
+
+ SwHandle = 0;
+ DEBUG ((EFI_D_INFO, " PpmS3SmmEntryPoint Started : \n"));
+ ///
+ /// Determine if we are in boot service or SMM.
+ ///
+ Status = gBS->LocateProtocol (&gEfiSmmBaseProtocolGuid, NULL, (VOID **) &SmmBase);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Initialize global variables
+ ///
+ Status = SmmBase->GetSmstLocation (SmmBase, &mSmst);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Locate platform configuration information
+ ///
+ Status = gBS->LocateProtocol (&gDxeCpuPlatformPolicyProtocolGuid, NULL, (VOID **) &mCpuPlatformPolicy);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Locate the ICH SMM SW dispatch protocol
+ ///
+ Status = gBS->LocateProtocol (&gEfiSmmSwDispatchProtocolGuid, NULL, (VOID **) &SwDispatch);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Register ACPI S3 MSR restore handler
+ ///
+ SwContext.SwSmiInputValue = mCpuPlatformPolicy->PowerMgmtConfig->S3RestoreMsrSwSmiNumber;
+
+ Status = SwDispatch->Register (
+ SwDispatch,
+ (EFI_SMM_SW_DISPATCH) S3RestoreMsr,
+ &SwContext,
+ &SwHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Save MSRs for S3 Resume.
+ ///
+ DEBUG ((EFI_D_INFO, " Saving Processor MSR for S3 Resume \n"));
+
+ S3SaveMsr ();
+
+ return EFI_SUCCESS;
+}
diff --git a/ReferenceCode/Haswell/PowerManagement/Smm/PowerMgmtS3.cif b/ReferenceCode/Haswell/PowerManagement/Smm/PowerMgmtS3.cif
new file mode 100644
index 0000000..8e974fc
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/Smm/PowerMgmtS3.cif
@@ -0,0 +1,13 @@
+<component>
+ name = "PowerMgmtS3"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\PowerManagement\Smm"
+ RefName = "PowerMgmtS3"
+[files]
+"PowerMgmtS3.mak"
+"PowerMgmtS3.sdl"
+"PowerMgmtS3.inf"
+"PowerMgmtS3.c"
+"PowerMgmtS3.dxs"
+"PowerMgmtS3.h"
+<endComponent>
diff --git a/ReferenceCode/Haswell/PowerManagement/Smm/PowerMgmtS3.dxs b/ReferenceCode/Haswell/PowerManagement/Smm/PowerMgmtS3.dxs
new file mode 100644
index 0000000..9a4a4a2
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/Smm/PowerMgmtS3.dxs
@@ -0,0 +1,45 @@
+/** @file
+ Dispatch dependency expression file for the PpmS3Dxe driver.
+
+@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 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 "AutoGen.h"
+#include "DxeDepex.h"
+
+//
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are both "defined" in R8 codebase;
+// BUILD_WITH_EDKII_GLUE_LIB is defined in Edk-Dev-Snapshot-20070228 and later version
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are "not defined" in R9 codebase.
+//
+#if defined (BUILD_WITH_GLUELIB) || defined (BUILD_WITH_EDKII_GLUE_LIB)
+#include "EfiDepex.h"
+
+//-#include EFI_PROTOCOL_DEFINITION (SmmControl)
+#include EFI_PROTOCOL_DEFINITION (SmmBase)
+#include EFI_PROTOCOL_DEPENDENCY (SmmSwDispatch)
+#include EFI_PROTOCOL_DEFINITION (PowerMgmtInitDone)
+#include EFI_PROTOCOL_DEFINITION (SaInfo)
+#endif
+
+DEPENDENCY_START
+ //-EFI_SMM_CONTROL_PROTOCOL_GUID AND
+ EFI_SMM_BASE_PROTOCOL_GUID AND
+ EFI_SMM_SW_DISPATCH_PROTOCOL_GUID AND
+ EFI_POWER_MGMT_INIT_DONE_PROTOCOL_GUID AND
+ EFI_SA_INFO_PROTOCOL_GUID
+DEPENDENCY_END
diff --git a/ReferenceCode/Haswell/PowerManagement/Smm/PowerMgmtS3.h b/ReferenceCode/Haswell/PowerManagement/Smm/PowerMgmtS3.h
new file mode 100644
index 0000000..211ef02
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/Smm/PowerMgmtS3.h
@@ -0,0 +1,68 @@
+/** @file
+ Header file for PpmS3 Smm Driver.
+
+@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
+**/
+#ifndef _POWER_MGMT_S3_SMM_H_
+#define _POWER_MGMT_S3_SMM_H_
+
+#include "EdkIIGlueDxe.h"
+#include "EfiScriptLib.h"
+#include "PchAccess.h"
+#include "PchPlatformLib.h"
+
+#define PPM_WAIT_PERIOD 15
+
+typedef struct _EFI_MSR_VALUES {
+ UINT16 Index;
+ UINT64 Value;
+ UINT64 BitMask;
+ BOOLEAN RestoreFlag;
+} EFI_MSR_VALUES;
+
+/**
+ Runs the specified procedure on all logical processors, passing in the
+ parameter buffer to the procedure.
+
+ @param[in] Procedure The function to be run.
+ @param[in] Buffer Pointer to a parameter buffer.
+
+ @retval EFI_SUCCESS
+**/
+STATIC
+EFI_STATUS
+RunOnAllLogicalProcessors (
+ IN OUT EFI_AP_PROCEDURE Procedure,
+ IN OUT VOID *Buffer
+ );
+/**
+ This function will restore MSR settings.
+
+ This function must be MP safe.
+
+ @param[in] Buffer Unused
+
+ @retval EFI_SUCCESS MSR restored
+**/
+VOID
+EFIAPI
+ApSafeRestoreMsr (
+ IN OUT VOID *Buffer
+ );
+
+#endif
diff --git a/ReferenceCode/Haswell/PowerManagement/Smm/PowerMgmtS3.inf b/ReferenceCode/Haswell/PowerManagement/Smm/PowerMgmtS3.inf
new file mode 100644
index 0000000..8b93a5d
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/Smm/PowerMgmtS3.inf
@@ -0,0 +1,97 @@
+## @file
+# Component description file for PowerManagementDxe driver
+#
+#@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 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
+#
+
+[defines]
+BASE_NAME = PowerMgmtS3
+FILE_GUID = 8F0B5301-C79B-44f1-8FD3-26D73E316700
+COMPONENT_TYPE = RT_DRIVER
+
+[sources.common]
+ PowerMgmtS3.h
+ PowerMgmtS3.c
+#
+# Edk II Glue Driver Entry Point
+#
+ EdkIIGlueSmmDriverEntryPoint.c
+
+[includes.common]
+ .
+ $(EFI_SOURCE)
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+ $(EFI_SOURCE)/Include
+ $(EFI_SOURCE)/Include/IndustryStandard
+ $(EFI_SOURCE)/Framework
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include/Library
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_SA_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_SA_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_SA_ROOT)/protocol
+
+[libraries.common]
+ CpuGuidLib
+ CpuProtocolLib
+ DxeAslUpdateLib
+ EfiProtocolLib
+ EdkFrameworkProtocolLib
+ EdkIIGlueBaseLib
+ EdkIIGlueBaseIoLibIntrinsic
+ EdkIIGlueBaseMemoryLib
+ EdkIIGlueDxeMemoryAllocationLib
+ EdkIIGlueDxeDebugLibReportStatusCode
+ EdkIIGlueSmmRuntimeDxeReportStatusCodeLib
+ EdkIIGlueUefiBootServicesTableLib
+ EdkIIGlueUefiRuntimeServicesTableLib
+ EdkIIGlueUefiDevicePathLib
+ EfiScriptLib
+ EdkProtocolLib
+ EfiRuntimeLib
+ PchPlatformLib
+ CpuPlatformLib
+
+[nmake.common]
+ IMAGE_ENTRY_POINT = _ModuleEntryPoint
+ DPX_SOURCE = PowerMgmtS3.dxs
+#
+# Module Entry Point
+#
+ C_FLAGS = $(C_FLAGS)-D __EDKII_GLUE_MODULE_ENTRY_POINT__=PowerMgmtS3SmmEntryPoint
+ C_FLAGS = $(C_FLAGS)-D __EDKII_GLUE_BASE_LIB__ \
+ -D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ -D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ -D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \
+ -D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ -D __EDKII_GLUE_SMM_RUNTIME_DXE_REPORT_STATUS_CODE_LIB__ \
+ -D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_UEFI_DEVICE_PATH_LIB__ \ No newline at end of file
diff --git a/ReferenceCode/Haswell/PowerManagement/Smm/PowerMgmtS3.mak b/ReferenceCode/Haswell/PowerManagement/Smm/PowerMgmtS3.mak
new file mode 100644
index 0000000..e534020
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/Smm/PowerMgmtS3.mak
@@ -0,0 +1,64 @@
+# MAK file for the Module Part: PowerMgmtS3
+
+EDK : PowerMgmtS3
+
+BUILD_PowerMgmtS3_DIR = $(BUILD_DIR)\$(PowerMgmtS3_DIR)
+
+$(BUILD_DIR)\PowerMgmtS3.mak : $(PowerMgmtS3_DIR)\PowerMgmtS3.cif $(BUILD_RULES)
+ $(CIF2MAK) $(PowerMgmtS3_DIR)\PowerMgmtS3.cif $(CIF2MAK_DEFAULTS)
+
+PowerMgmtS3 : $(BUILD_DIR)\PowerMgmtS3.mak PowerMgmtS3Bin
+
+PowerMgmtS3_OBJECTS = \
+ $(BUILD_PowerMgmtS3_DIR)\PowerMgmtS3.obj
+
+
+PowerMgmtS3_MY_INCLUDES= \
+ $(EDK_INCLUDES) \
+ $(PROJECT_CPU_INCLUDES)\
+ $(INTEL_PCH_INCLUDES)\
+ $(INTEL_MCH_INCLUDES)
+
+
+PowerMgmtS3_DEFINES = $(MY_DEFINES)\
+ /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=PowerMgmtS3SmmEntryPoint"\
+ /D __EDKII_GLUE_BASE_LIB__ \
+ /D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ /D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ /D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \
+ /D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ /D __EDKII_GLUE_SMM_RUNTIME_DXE_REPORT_STATUS_CODE_LIB__ \
+ /D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \
+ /D __EDKII_GLUE_UEFI_DEVICE_PATH_LIB__
+
+PowerMgmtS3_LIBS =\
+ $(EFIGUIDLIB)\
+ $(EDKFRAMEWORKGUIDLIB)\
+ $(EDKPROTOCOLLIB)\
+ $(EDKFRAMEWORKPROTOCOLLIB)\
+ $(EdkIIGlueBaseLib_LIB)\
+ $(EdkIIGlueBaseMemoryLib_LIB)\
+ $(EdkIIGlueDxeReportStatusCodeLib_LIB)\
+ $(EdkIIGlueDxeDebugLibReportStatusCode_LIB)\
+ $(EdkIIGlueSmmRuntimeDxeReportStatusCodeLib_LIB)\
+ $(EdkIIGlueUefiBootServicesTableLib_LIB)\
+ $(EdkIIGlueBasePciLibPciExpress_LIB)\
+ $(CpuProtocolLib_LIB)\
+ $(CpuPlatformLib_LIB)\
+ $(PchPlatformSmmLib_LIB)
+
+PowerMgmtS3Bin : $(PowerMgmtS3_LIBS)
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\PowerMgmtS3.mak all\
+ MAKEFILE=$(BUILD_DIR)\PowerMgmtS3.mak \
+ "MY_INCLUDES=$(PowerMgmtS3_MY_INCLUDES)" \
+ "MY_DEFINES=$(PowerMgmtS3_DEFINES)"\
+ OBJECTS="$(PowerMgmtS3_OBJECTS)" \
+ GUID=8F0B5301-C79B-44f1-8FD3-26D73E316700\
+ ENTRY_POINT=_ModuleEntryPoint \
+ TYPE=RT_DRIVER \
+ EDKIIModule=SMMDRIVER\
+ DEPEX1=$(PowerMgmtS3_DIR)\PowerMgmtS3.dxs \
+ DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX \
+ COMPRESS=1
+
diff --git a/ReferenceCode/Haswell/PowerManagement/Smm/PowerMgmtS3.sdl b/ReferenceCode/Haswell/PowerManagement/Smm/PowerMgmtS3.sdl
new file mode 100644
index 0000000..513e535
--- /dev/null
+++ b/ReferenceCode/Haswell/PowerManagement/Smm/PowerMgmtS3.sdl
@@ -0,0 +1,25 @@
+TOKEN
+ Name = "Haswell_PowerMgmtS3_SUPPORT"
+ Value = "1"
+ Help = "Main switch to include CPU RC PowerMgmtS3 driver to the Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+End
+
+PATH
+ Name = "PowerMgmtS3_DIR"
+End
+
+MODULE
+ Help = "Includes PowerMgmtS3.mak to Project"
+ File = "PowerMgmtS3.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\PowerMgmtS3.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End
diff --git a/ReferenceCode/Haswell/Ppi/Cache/Cache.c b/ReferenceCode/Haswell/Ppi/Cache/Cache.c
new file mode 100644
index 0000000..75e8535
--- /dev/null
+++ b/ReferenceCode/Haswell/Ppi/Cache/Cache.c
@@ -0,0 +1,25 @@
+/** @file
+ CPU IO PPI GUID as defined in EFI 2.0
+
+@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 'Framework Code' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may not be modified, except as allowed by
+ additional terms of your license agreement.
+**/
+#include "Tiano.h"
+#include "Pei.h"
+#include EFI_PPI_DEFINITION (Cache)
+
+EFI_GUID gPeiCachePpiGuid = PEI_CACHE_PPI_GUID;
+
+EFI_GUID_STRING(&gPeiCachePpiGuid, "Cache", "Cache PPI");
diff --git a/ReferenceCode/Haswell/Ppi/Cache/Cache.h b/ReferenceCode/Haswell/Ppi/Cache/Cache.h
new file mode 100644
index 0000000..cbd846b
--- /dev/null
+++ b/ReferenceCode/Haswell/Ppi/Cache/Cache.h
@@ -0,0 +1,86 @@
+/** @file
+ Cache PPI defined in EFI 2.0
+ This code abstracts Cache Settings
+
+@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 'Framework Code' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may not be modified, except as allowed by
+ additional terms of your license agreement.
+**/
+#ifndef _PEI_CACHE_PPI_H_
+#define _PEI_CACHE_PPI_H_
+
+#define PEI_CACHE_PPI_GUID \
+ { \
+ 0x9be4bc2, 0x790e, 0x4dea, 0x8b, 0xdc, 0x38, 0x5, 0x16, 0x98, 0x39, 0x44 \
+ }
+
+EFI_FORWARD_DECLARATION (PEI_CACHE_PPI);
+
+typedef enum _EFI_MEMORY_CACHE_TYPE
+{
+ EfiCacheTypeUncacheable = 0,
+ EfiCacheTypeWriteCombining= 1,
+ EfiCacheTypeReserved2 = 2,
+ EfiCacheTypeReserved3 = 3,
+ EfiCacheTypeWriteThrough = 4,
+ EfiCacheTypeWriteProtected= 5,
+ EfiCacheTypeWriteBack = 6,
+ EfiCacheTypeMaximumType = 7
+} EFI_MEMORY_CACHE_TYPE;
+
+typedef
+EFI_STATUS
+(EFIAPI *PEI_SET_CACHE_PPI)(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_CACHE_PPI *This,
+ IN EFI_PHYSICAL_ADDRESS MemoryAddress,
+ IN UINT64 MemoryLength,
+ IN EFI_MEMORY_CACHE_TYPE MemoryCacheType
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *PEI_RESET_CACHE_PPI)(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_CACHE_PPI *This
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *PEI_ACTIVATE_CACHE_PPI)(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN PEI_CACHE_PPI *This
+ );
+
+///
+/// Platform code can use this interface to arrange MTRR configuration in PEI phase.
+///
+struct _PEI_CACHE_PPI {
+ ///
+ /// Set MTRR configuration for a memory region.
+ ///
+ PEI_SET_CACHE_PPI SetCache;
+ ///
+ /// Clean up MTRR in MTRR buffer.
+ ///
+ PEI_RESET_CACHE_PPI ResetCache;
+ ///
+ /// Disable NEM if in NEM mode, and sync MTRR configuration from buffer to MSR.
+ ///
+ PEI_ACTIVATE_CACHE_PPI ActivateCache;
+};
+
+extern EFI_GUID gPeiCachePpiGuid;
+
+#endif
diff --git a/ReferenceCode/Haswell/Ppi/CpuPlatformPolicy/CpuPlatformPolicy.c b/ReferenceCode/Haswell/Ppi/CpuPlatformPolicy/CpuPlatformPolicy.c
new file mode 100644
index 0000000..61cf0be
--- /dev/null
+++ b/ReferenceCode/Haswell/Ppi/CpuPlatformPolicy/CpuPlatformPolicy.c
@@ -0,0 +1,43 @@
+/** @file
+ CPU policy PPI produced by a platform driver specifying various
+ expected CPU settings. This protocol is consumed by the CPU PEI modules.
+
+@copyright
+ Copyright (c) 2009 - 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
+**/
+
+///
+/// Statements that include other files
+///
+///
+/// External include files do NOT need to be explicitly specified in real EDKII
+/// environment
+///
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+
+#include "EdkIIGluePeim.h"
+#endif
+
+#include "CpuPlatformPolicy.h"
+
+///
+/// Protocol GUID definition
+///
+EFI_GUID gPeiCpuPlatformPolicyPpiGuid = PEI_CPU_PLATFORM_POLICY_PPI_GUID;
+
+///
+/// Protocol description
+///
+EFI_GUID_STRING(&gPeiCpuPlatformPolicyPpiGuid, "CpuPlatformPolicy PPI", "Intel(R) PEI Phase CPU Platform Policy PPI");
diff --git a/ReferenceCode/Haswell/Ppi/CpuPlatformPolicy/CpuPlatformPolicy.h b/ReferenceCode/Haswell/Ppi/CpuPlatformPolicy/CpuPlatformPolicy.h
new file mode 100644
index 0000000..55c8890
--- /dev/null
+++ b/ReferenceCode/Haswell/Ppi/CpuPlatformPolicy/CpuPlatformPolicy.h
@@ -0,0 +1,358 @@
+/** @file
+ CPU policy PPI produced by a platform driver specifying various
+ expected CPU settings. This PPI is consumed by CPU PEI modules.
+
+@copyright
+ Copyright (c) 2009 - 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
+**/
+#ifndef CPU_PLATFORM_POLICY_H_
+#define CPU_PLATFORM_POLICY_H_
+
+#include "PfatDefinitions.h"
+
+//
+// CPU policy provided by platform for PEI phase
+//
+//
+// EDK and EDKII have different GUID formats
+//
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#define PEI_CPU_PLATFORM_POLICY_PPI_GUID \
+ { \
+ 0xf8d5438e, 0x26e1, 0x481d, 0xb6, 0x3c, 0x30, 0xd6, 0xef, 0xf4, 0xa4, 0x20 \
+ }
+#else
+#define PEI_CPU_PLATFORM_POLICY_PPI_GUID \
+ { \
+ 0xf8d5438e, 0x26e1, 0x481d, \
+ { \
+ 0xb6, 0x3c, 0x30, 0xd6, 0xef, 0xf4, 0xa4, 0x20 \
+ } \
+ }
+#endif
+
+extern EFI_GUID gPeiCpuPlatformPolicyPpiGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PEI_CPU_PLATFORM_POLICY_PPI PEI_CPU_PLATFORM_POLICY_PPI;
+
+#define CPU_FEATURE_ENABLE 1
+#define CPU_FEATURE_DISABLE 0
+
+///
+/// PPI revision number
+/// Any backwards compatible changes to this PPI will result in an update in the revision number
+/// Major changes will require publication of a new PPI
+///
+
+///
+///Revision 1: Original version
+///
+#define PEI_CPU_PLATFORM_POLICY_PPI_REVISION_1 1
+///
+///Revision 2: Added policies for PFAT-BIOS-EC Interface to PFAT_CONFIG
+/// Added PfatLog to PFAT_CONFIG
+#define PEI_CPU_PLATFORM_POLICY_PPI_REVISION_2 2
+///
+///Revision 3: Added VR_MISC MSR configuration policies
+/// POWER_MGMT_CONFIG.VrMiscMinVid;
+/// POWER_MGMT_CONFIG.VrMiscIdleExitRampRate;
+/// POWER_MGMT_CONFIG.VrMiscIdleEntryRampRate;
+/// POWER_MGMT_CONFIG.VrMiscIdleEntryDecayEnable;
+/// POWER_MGMT_CONFIG.VrMiscSlowSlewRateConfig;
+/// Added VR_MISC2 MSR configuration policies
+/// POWER_MGMT_CONFIG.VrMisc2FastRampVoltage;
+/// POWER_MGMT_CONFIG.VrMisc2MinC8Voltage;
+/// Extended POWER_MGMT_CONFIG.BootInLfm settings from 0(HFM)/ 1(LFM) to 0(HFM)/ 1(LFM)/ 2(TURBO)
+///
+#define PEI_CPU_PLATFORM_POLICY_PPI_REVISION_3 3
+///
+///Revision 4: Added VR_MISC MSR configuration policies
+/// POWER_MGMT_CONFIG.VrMiscIoutSlope;
+/// POWER_MGMT_CONFIG.VrMiscIoutOffsetSign;
+/// POWER_MGMT_CONFIG.VrMiscIoutOffset;
+///
+#define PEI_CPU_PLATFORM_POLICY_PPI_REVISION_4 4
+///
+///Revision 5: Added POWER_MGMT_CONFIG_PPI policies
+/// POWER_MGMT_CONFIG_PPI.VrPSI4enable;
+/// POWER_MGMT_CONFIG_PPI.Psi1Threshold;
+/// POWER_MGMT_CONFIG_PPI.Psi2Threshold;
+/// POWER_MGMT_CONFIG_PPI.Psi3Threshold;
+///
+#define PEI_CPU_PLATFORM_POLICY_PPI_REVISION_5 5
+///
+///Revision 6: Added POWER_MGMT_CONFIG_PPI Fivr polcies
+/// POWER_MGMT_CONFIG_PPI.FivrSscEnable
+/// POWER_MGMT_CONFIG_PPI.FivrSscPercent
+///
+#define PEI_CPU_PLATFORM_POLICY_PPI_REVISION_6 6
+///
+///Revision 7: Added CpuPlatformPpiPtr
+/// BOOT_GUARD_CONFIG.BootGuardSupport
+/// BOOT_GUARD_CONFIG.DisconnectAllTpms
+///
+#define PEI_CPU_PLATFORM_POLICY_PPI_REVISION_7 7
+///
+///Revision 8: Added BOOT_GUARD_CONFIG configuration policies
+/// BOOT_GUARD_CONFIG.ByPassTpmEventLog
+///
+#define PEI_CPU_PLATFORM_POLICY_PPI_REVISION_8 8
+
+///
+/// General CPU features configration for all processor features enabling / configuration bit definitions are in
+/// this field. Platform code can enable/disable/configure features thru this field.
+///
+typedef struct {
+ //
+ // Byte 0, bit definition for functionality enable/disable
+ //
+ UINT8 BistOnReset : 1; ///< Enable or Disable BIST on Reset.
+ UINT8 HyperThreading : 1; ///< Enable or Disable Hyper Threading.
+ UINT8 CpuRatioOverride : 1; ///< Enable or Disable CPU Radio Override.
+ UINT8 VmxEnable : 1; ///< Enable or Disable VMX.
+ UINT8 Pfat : 1; ///< Enable or Disable PFAT.
+ UINT8 MlcStreamerPrefetcher : 1; ///< Enable or Disable MLC Streamer Prefetcher.
+ UINT8 MlcSpatialPrefetcher : 1; ///< Enable or Disable MLC Spatial Prefetcher.
+ UINT8 Txt : 1; ///< Enable or Disable TXT.
+
+ //
+ // Byte 1, bit definition for functionality enable/disable
+ //
+ UINT8 Rsvdbyte : 8; ///< A place holder for additonal functionalites expected in futture platforms.
+ //
+ // Generic CPU feature configuration
+ //
+ UINT8 ActiveCoreCount; ///< Number of active cores.
+ UINT8 CpuRatio; ///< CPU ratio value
+ UINT8 CpuMaxNonTurboRatio; ///< CPU Maximum Non-Turbo ratio value
+} CPU_CONFIG_PPI;
+
+///
+/// Power management Configuration for all Processor Power Management Features
+/// Configs are in this field. Platform code can enable/disable features thru this field.
+///
+typedef struct {
+ UINT8 BootInLfm; ///< Boot in Low-Frequency-Mode.
+ ///
+ /// TCC Activation Offset. Offset from factory set TCC activation temperature at which the Thermal Control Circuit
+ /// must be activated. TCC will be activated at TCC Activation Temp V TCC Activation Offset.
+ ///
+ UINT8 TccActivationOffset;
+ ///
+ /// MSR 0x601[12:0], Primary (IA) Current Limit, in 1/8 A units, 0=Auto. Maximum instantaneous current allowed at
+ /// any given time. Setting a value too far below the Iccmax specification for this platform/CPU might result
+ /// in System hang / CATERR / BSOD depending on the platform configuration.
+ ///
+ UINT16 VrCurrentLimit;
+ UINT8 VrCurrentLimitLock; ///< MSR 0x601[31]: when set, locks bits 31:0 of this MSR.
+ UINT8 Xe; ///< Enable or Disable Intel Extreme Edition support.
+ ///
+ /// 1-Core Ratio Limit: For XE part: LFM to 255, For overclocking part: LFM to Fused 1-Core Ratio Limit + OC Bins.
+ /// This 1-Core Ratio Limit Must be greater than or equal to 2-Core Ratio Limit, 3-Core Ratio Limit, 4-Core
+ /// Ratio Limit.
+ /// 2-Core Ratio Limit: For XE part: LFM to 255, For overclocking part: LFM to Fused 2-Core Ratio Limit + OC Bins.
+ /// This 2-Core Ratio Limit Must be Less than or equal to 1-Core Ratio Limit.
+ /// 3-Core Ratio Limit: For XE part: LFM to 255, For overclocking part: LFM to Fused 3-Core Ratio Limit + OC Bins.
+ /// This 3-Core Ratio Limit Must be Less than or equal to 1-Core Ratio Limit.
+ /// 4-Core Ratio Limit: For XE part: LFM to 255, For overclocking part: LFM to Fused 4-Core Ratio Limit + OC Bins.
+ /// This 4-Core Ratio Limit Must be Less than or equal to 1-Core Ratio Limit.
+ ///
+ UINT8 RatioLimit[4];
+ UINT8 VrMiscMinVid; ///< MSR 0x603[31:24]: Used to constrain the CPU's minimum voltage during package C-states.
+ UINT8 VrMiscIdleExitRampRate; ///< MSR 0x603[50]: Controls the VR ramp rate on package C-state wake events.
+ UINT8 VrMiscIdleEntryRampRate; ///< MSR 0x603[51]: Controls the VR ramp rate on package C-state entry events.
+ UINT8 VrMiscIdleEntryDecayEnable; ///< MSR 0x603[52]: Enables decay mode on package C-state entry.
+ UINT8 VrMiscSlowSlewRateConfig; ///< MSR 0x53[54:53]: Slow Slew rate configuration.
+ UINT8 VrMisc2FastRampVoltage; ///< MSR 0x636[7:0]: Update FAST_RAMP_VOLTAGE; must be 0 to 0xFF, resolution 10mV.
+ UINT8 VrMisc2MinC8Voltage; ///< MSR 0x636[15:8]: Update MIN_C8_VOLTAGE; must be 0 to 0xFF, resolution 10mV.
+ UINT16 VrMiscIoutSlope; ///< MSR 0x603[49-40]: IOUT SLOPE. Default is 200.
+ UINT8 VrMiscIoutOffsetSign; ///< IOUT OFFSET Sign. 0 = positive offset. 1= negative offset.
+ UINT16 VrMiscIoutOffset; ///< MSR 0x603[39-32]: IOUT_OFFSET. 0 = 0%, 625 = 6.25% (Range is +6.25% ~ -6.25%)
+ UINT8 VrPSI4enable; ///< MSR 0x601[62]: PSI4 Enabled/Disabled bit in VR_CURRENT_CONFIG, it's only applied to HSW ULT.
+ UINT8 Psi1Threshold; ///< MSR 0x601[41:32]: Current Threshold for PSI1_CODE specified in Amps.
+ UINT8 Psi2Threshold; ///< MSR 0x601[51:42]: Current Threshold for PSI2_CODE specified in Amps.
+ UINT8 Psi3Threshold; ///< MSR 0x601[61:52]: Current Threshold for PSI3_CODE specified in Amps.
+ UINT8 FivrSscEnable; ///< Enable/Disable FIVR Spread Spectrum support
+ UINT8 FivrSscPercent; ///< PCODE MMIO Mailbox: FIVR spread spectrum percentage value.
+} POWER_MGMT_CONFIG_PPI;
+
+///
+/// PFAT Configuration for all processor security features configuration structures
+/// are in this field. Platform code can pass relevant configuration data thru this field.
+///
+typedef struct {
+ ///
+ /// PFAT update package header that will be packaged along with PFAT script and update data.
+ ///
+ PUP_HEADER PupHeader;
+ ///
+ /// PFAT Platform Data Table contains all the platform data that will be parsed by PFAT module.
+ ///
+ PPDT Ppdt;
+ UINT64 PpdtHash[4]; ///< Hash of the PPDT that will be programmed to PLAT_FRMW_PROT_HASH_0/1/2/3 MSR.
+ UINT8 NumSpiComponents; ///< Number of SPI flash components on platform.
+ UINT8 ComponentSize[MAX_SPI_COMPONENTS]; ///< Size of each flash component on platform.
+ UINT8 PfatMemSize; ///< PFAT memory size.
+ UINT8 EcCmdDiscovery; ///< EC Command discovery.
+ UINT8 EcCmdProvisionEav; ///< EC Command Provision Eav.
+ UINT8 EcCmdLock; ///< EC Command Lock.
+ PFAT_LOG PfatLog; ///< PFAT log.
+} PFAT_CONFIG;
+
+//
+// TxT Configuraion Policy
+//
+#define TXT_SINIT_MEMORY_SIZE 0x20000
+#define TXT_HEAP_MEMORY_SIZE 0xE0000
+#define TXT_DPR_MEMORY_SIZE 0x400000
+#define TXT_DEVICE_MEMORY_SIZE (TXT_SINIT_MEMORY_SIZE + TXT_HEAP_MEMORY_SIZE)
+
+#define TXT_LCP_PD_BASE 0x0 ///< Platform default LCP
+#define TXT_LCP_PD_SIZE 0x0 ///< Platform default LCP
+#define TXT_TGA_MEMORY_SIZE 0x0 ///< Maximum 512K of TGA memory (aperture)
+#define TXT_TGTT_MEMORY_SIZE 0x80000 ///< 512K of TGTT memory
+#define TXT_TGR_MEMORY_SIZE 0x80000 ///< 512K of TGR memory (Registers)
+#define TXT_TOTAL_STOLEN_MEMORY_SIZE (TXT_DPR_MEMORY_SIZE)
+
+typedef struct {
+ UINT64 SinitMemorySize; ///< Size of SINIT module if installed in flash part. Zero otherwise.
+ UINT64 TxtHeapMemorySize; ///< Size of memory reserved for TXT Heap. This memory is used by MLE.
+ EFI_PHYSICAL_ADDRESS TxtDprMemoryBase; ///< Base address of DPR protected memory reserved for Intel TXT component.
+ UINT64 TxtDprMemorySize; ///< Size of DPR protected memory reserved for Intel TXT component.
+ ///
+ /// Base address of BIOS ACM in flash part. It can be passed through platform code for customization; Intel TXT
+ /// reference code would skip searching the BIOS ACM in PEI firmware volume if the field is not zero.
+ ///
+ EFI_PHYSICAL_ADDRESS BiosAcmBase;
+ UINT64 BiosAcmSize; ///< Size of ACM Binary.
+ ///
+ /// Base address of CPU micro code patch loaded into BSP. It can be passed through platform code for customization;
+ /// Intel TXT reference code would skip searching the micro code path in PEI firmware volume if the field is not zero.
+ ///
+ EFI_PHYSICAL_ADDRESS McuUpdateDataAddr;
+ ///
+ /// Size of Trusted Graphics Aperture if supported by chipset. For Cantiga must be 0.
+ ///
+ UINT64 TgaSize;
+ ///
+ /// Base address of Platform Default Launch Control Policy data if installed in flash part. Zero otherwise.
+ ///
+ EFI_PHYSICAL_ADDRESS TxtLcpPdBase;
+ ///
+ /// Size of Platform Default Launch Control Policy data if installed in flash part. Zero otherwise.
+ ///
+ UINT64 TxtLcpPdSize;
+} TXT_CONFIG;
+
+//
+// Boot Guard Configuration
+//
+typedef enum {
+ TpmNone = 0,
+ dTpm12,
+ dTpm20,
+ Ptt,
+ TpmTypeMax
+} TPM_TYPE;
+
+typedef struct {
+ BOOLEAN MeasuredBoot;
+ BOOLEAN BypassTpmInit;
+ TPM_TYPE TpmType;
+ BOOLEAN BootGuardSupport;
+ BOOLEAN DisconnectAllTpms;
+ BOOLEAN ByPassTpmEventLog;
+} BOOT_GUARD_CONFIG;
+
+///
+/// Security Configuration
+///
+typedef struct {
+ PFAT_CONFIG *PfatConfig; ///< PFAT Configuration settings.
+ TXT_CONFIG *TxtConfig; ///< TxT Configuration settings.
+ BOOT_GUARD_CONFIG *BootGuardConfig; ///< Boot Guard Configuration settings.
+} SECURITY_CONFIG_PPI;
+
+///
+/// Overclocking Configuration controls which use the CPU overclocking mailbox interface are defined in this structure.
+/// Platform code can pass in data to the mailbox through this structure.
+///
+typedef struct {
+ INT16 CoreVoltageOffset; ///< The voltage offset applied to the core while operating in turbo mode.
+ ///
+ /// The core voltage override which is applied to the entire range of cpu core frequencies.
+ ///
+ UINT16 CoreVoltageOverride;
+ ///
+ /// Extra Turbo voltage applied to the cpu core when the cpu is operating in turbo mode.
+ ///
+ UINT16 CoreExtraTurboVoltage;
+ ///
+ /// Maximum core turbo ratio override allows to increase CPU core frequency beyond the fused max turbo ratio limit.
+ ///
+ UINT16 CoreMaxOcTurboRatio;
+ INT16 ClrVoltageOffset; ///< The voltage offset applied to CLR while operating in turbo mode.
+ UINT16 ClrVoltageOverride; ///< The clr voltage override which is applied to the entire range of cpu frequencies.
+ UINT16 ClrExtraTurboVoltage; ///< Extra Turbo voltage applied to clr.
+ ///
+ /// Maximum clr turbo ratio override allows to increase CPU clr frequency beyond the fused max turbo ratio limit.
+ ///
+ UINT16 ClrMaxOcTurboRatio;
+ UINT16 SvidVoltageOverride; ///< Overrides the VR voltage through SVID bus to apply a new input voltage to the cpu.
+ UINT8 SvidEnable : 1; ///< Enable or Disable SVID communication from FIVR to the external VR.
+ UINT8 FivrFaultsEnable : 1; ///< Enable or Disable FIVR Fault management.
+ UINT8 FivrEfficiencyEnable : 1; ///< Enable or Disable FIVR efficiency.
+ UINT8 CoreVoltageMode : 1; ///< 0: Adaptive, 1: Override
+ UINT8 ClrVoltageMode : 1; ///< 0: Adaptive, 1:Override
+ UINT8 OcSupport : 1; ///< 0: Disable, 1: Enable
+ UINT8 BitReserved : 2; ///< Bits reserved for future use
+} OVERCLOCKING_CONFIG_PPI;
+
+///
+/// CPU Platform Policy PPI definition, this PPI provides interface to configure
+/// the processor. Platform code needs to configure the policies for processor
+/// ref code to finish the initialization.
+///
+struct _PEI_CPU_PLATFORM_POLICY_PPI {
+ ///
+ /// Revision for the PPI structure.
+ ///
+ UINT8 Revision;
+ ///
+ /// Processor Features Configuration.
+ ///
+ CPU_CONFIG_PPI *CpuConfig;
+ ///
+ /// Processor Power ManagementFeatures Configuration.
+ ///
+ POWER_MGMT_CONFIG_PPI *PowerMgmtConfig;
+ ///
+ /// Processor Security features Configuration.
+ ///
+ SECURITY_CONFIG_PPI *SecurityConfig;
+ ///
+ /// Processor OverClocking features Configuration.
+ ///
+ OVERCLOCKING_CONFIG_PPI *OverclockingConfig;
+ ///
+ /// PEI_CPU_PLATFORM_POLICY_PPI Ptr.
+ ///
+ UINTN CpuPlatformPpiPtr;
+};
+
+#endif
diff --git a/ReferenceCode/Haswell/Ppi/CpuPpiLib.cif b/ReferenceCode/Haswell/Ppi/CpuPpiLib.cif
new file mode 100644
index 0000000..fe862f1
--- /dev/null
+++ b/ReferenceCode/Haswell/Ppi/CpuPpiLib.cif
@@ -0,0 +1,18 @@
+<component>
+ name = "CpuPpiLib"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\Ppi\"
+ RefName = "CpuPpiLib"
+[files]
+"CpuPpiLib.sdl"
+"CpuPpiLib.mak"
+"CpuPpiLib.inf"
+"Cache\Cache.c"
+"Cache\Cache.h"
+"CpuPlatformPolicy\CpuPlatformPolicy.c"
+"CpuPlatformPolicy\CpuPlatformPolicy.h"
+"TxtMemoryUnlocked\TxtMemoryUnlocked.c"
+"TxtMemoryUnlocked\TxtMemoryUnlocked.h"
+"TpmInitialized\TpmInitialized.c"
+"TpmInitialized\TpmInitialized.h"
+<endComponent>
diff --git a/ReferenceCode/Haswell/Ppi/CpuPpiLib.inf b/ReferenceCode/Haswell/Ppi/CpuPpiLib.inf
new file mode 100644
index 0000000..7d348d0
--- /dev/null
+++ b/ReferenceCode/Haswell/Ppi/CpuPpiLib.inf
@@ -0,0 +1,65 @@
+## @file
+# Component description file for CPU PPI library.
+#
+#@copyright
+# Copyright (c) 2005 - 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
+#
+
+[defines]
+BASE_NAME = CpuPpiLib
+COMPONENT_TYPE = LIBRARY
+
+[includes.common]
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Pei/Include
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include
+
+#
+# Edk II Glue Library, some hearder are included by R9 header so have to include
+#
+ $(EFI_SOURCE)
+ $(EFI_SOURCE)/Framework
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+
+[sources.common]
+ Cache/Cache.c
+ Cache/Cache.h
+ CpuPlatformPolicy/CpuPlatformPolicy.c
+ CpuPlatformPolicy/CpuPlatformPolicy.h
+ TxtMemoryUnlocked/TxtMemoryUnlocked.c
+ TxtMemoryUnlocked/TxtMemoryUnlocked.h
+ TpmInitialized/TpmInitialized.c
+ TpmInitialized/TpmInitialized.h
+
+[nmake.common]
+C_STD_INCLUDE=
+
diff --git a/ReferenceCode/Haswell/Ppi/CpuPpiLib.mak b/ReferenceCode/Haswell/Ppi/CpuPpiLib.mak
new file mode 100644
index 0000000..e5dc158
--- /dev/null
+++ b/ReferenceCode/Haswell/Ppi/CpuPpiLib.mak
@@ -0,0 +1,21 @@
+# MAK file for the ModulePart:IntelSaPpiLib
+EDK : CpuPpiLib
+
+$(BUILD_DIR)\CpuPpiLib.lib : CpuPpiLib
+
+CpuPpiLib : $(BUILD_DIR)\CpuPpiLib.mak CpuPpiLibBin
+
+$(BUILD_DIR)\CpuPpiLib.mak : $(CPU_PPI_LIB_DIR)\$(@B).cif $(CPU_PPI_LIB_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(CPU_PPI_LIB_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+CpuPpiLib_INCLUDES =\
+ $(PROJECT_CPU_INCLUDES)\
+ $(EDK_INCLUDES) \
+ $(INTEL_MCH_INCLUDES)
+
+CpuPpiLibBin :
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\CpuPpiLib.mak all\
+ "MY_INCLUDES=$(CpuPpiLib_INCLUDES)" \
+ TYPE=PEI_LIBRARY \
+ LIBRARY_NAME=$(CPU_PPI_LIB) \ No newline at end of file
diff --git a/ReferenceCode/Haswell/Ppi/CpuPpiLib.sdl b/ReferenceCode/Haswell/Ppi/CpuPpiLib.sdl
new file mode 100644
index 0000000..096d206
--- /dev/null
+++ b/ReferenceCode/Haswell/Ppi/CpuPpiLib.sdl
@@ -0,0 +1,31 @@
+TOKEN
+ Name = CpuPpiLib_SUPPORT
+ Value = "1"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+ Help = "Main switch to enable SaPpiLib support in Project"
+End
+
+MODULE
+ Help = "Includes SaPpiLib.mak to Project"
+ File = "CpuPpiLib.mak"
+End
+
+ELINK
+ Name = "CPU_PPI_LIB"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\CpuPpiLib.lib"
+ Parent = "CPU_PPI_LIB"
+ InvokeOrder = AfterParent
+End
+
+PATH
+ Name = "CPU_PPI_LIB_DIR"
+End
+
+
diff --git a/ReferenceCode/Haswell/Ppi/TpmInitialized/TpmInitialized.c b/ReferenceCode/Haswell/Ppi/TpmInitialized/TpmInitialized.c
new file mode 100644
index 0000000..958301b
--- /dev/null
+++ b/ReferenceCode/Haswell/Ppi/TpmInitialized/TpmInitialized.c
@@ -0,0 +1,24 @@
+/** @file
+ Tpm Initialized PPI
+
+@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 EFI_PPI_DEFINITION (TpmInitialized)
+
+EFI_GUID gPeiTpmInitializedPpiGuid = PEI_TPM_INITIALIZED_PPI_GUID;
+
+EFI_GUID_STRING(&gPeiTpmInitializedPpiGuid, "TpmInitialized PPI", "TpmInitialized PPI");
diff --git a/ReferenceCode/Haswell/Ppi/TpmInitialized/TpmInitialized.h b/ReferenceCode/Haswell/Ppi/TpmInitialized/TpmInitialized.h
new file mode 100644
index 0000000..27c09c9
--- /dev/null
+++ b/ReferenceCode/Haswell/Ppi/TpmInitialized/TpmInitialized.h
@@ -0,0 +1,29 @@
+/** @file
+ Tpm Initialized PPI definition, used to notify any code after TPM initialized.
+
+@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
+**/
+#ifndef _PEI_TPM_INITIALIZED_PPI_H_
+#define _PEI_TPM_INITIALIZED_PPI_H_
+
+#define PEI_TPM_INITIALIZED_PPI_GUID \
+ { \
+ 0xe9db0d58, 0xd48d, 0x47f6, 0x9c, 0x6e, 0x6f, 0x40, 0xe8, 0x6c, 0x7b, 0x41 \
+ }
+
+extern EFI_GUID gPeiTpmInitializedPpiGuid;
+
+#endif
diff --git a/ReferenceCode/Haswell/Ppi/TxtMemoryUnlocked/TxtMemoryUnlocked.c b/ReferenceCode/Haswell/Ppi/TxtMemoryUnlocked/TxtMemoryUnlocked.c
new file mode 100644
index 0000000..d905414
--- /dev/null
+++ b/ReferenceCode/Haswell/Ppi/TxtMemoryUnlocked/TxtMemoryUnlocked.c
@@ -0,0 +1,33 @@
+/** @file
+ This file contains GUID to use for defining of TXT Memory Unlocked PPI.
+
+@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 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
+**/
+
+///
+/// External include files do NOT need to be explicitly specified in real EDKII
+/// environment
+///
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGluePeim.h"
+#include EFI_PPI_DEFINITION (TxtMemoryUnlocked)
+#endif
+
+EFI_GUID gPeiTxtMemoryUnlockedPpiGuid = PEI_TXT_MEMORY_UNLOCKED_PPI_GUID;
+
+EFI_GUID_STRING(&gPeiTxtMemoryUnlockedPpiGuid, "TXT PPI", "TXT PPI");
diff --git a/ReferenceCode/Haswell/Ppi/TxtMemoryUnlocked/TxtMemoryUnlocked.h b/ReferenceCode/Haswell/Ppi/TxtMemoryUnlocked/TxtMemoryUnlocked.h
new file mode 100644
index 0000000..8b1be06
--- /dev/null
+++ b/ReferenceCode/Haswell/Ppi/TxtMemoryUnlocked/TxtMemoryUnlocked.h
@@ -0,0 +1,32 @@
+/** @file
+ This file contains PPI definition that is installed
+ by TXT PEIM
+
+@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 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
+**/
+#ifndef _PEI_TXT_MEMORY_UNLOCKED_PPI_H_
+#define _PEI_TXT_MEMORY_UNLOCKED_PPI_H_
+
+#define PEI_TXT_MEMORY_UNLOCKED_PPI_GUID \
+ { \
+ 0x38cdd10b, 0x767d, 0x4f6e, 0xa7, 0x44, 0x67, 0xee, 0x1d, 0xfe, 0x2f, 0xa5 \
+ }
+
+extern EFI_GUID gPeiTxtMemoryUnlockedPpiGuid;
+
+#endif
diff --git a/ReferenceCode/Haswell/Protocol/CpuInfo/CpuInfo.c b/ReferenceCode/Haswell/Protocol/CpuInfo/CpuInfo.c
new file mode 100644
index 0000000..01f84c5
--- /dev/null
+++ b/ReferenceCode/Haswell/Protocol/CpuInfo/CpuInfo.c
@@ -0,0 +1,25 @@
+/** @file
+ Protocol used for CPU driver to provide the CPU information.
+
+@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 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
+**/
+#include "Tiano.h"
+#include EFI_PROTOCOL_DEFINITION (CpuInfo)
+
+EFI_GUID gDxeCpuInfoProtocolGuid = DXE_CPU_INFO_PROTOCOL_GUID;
+
+EFI_GUID_STRING(&gDxeCpuInfoProtocolGuid, "CPU Information", "CPU information from CPU Drivers");
diff --git a/ReferenceCode/Haswell/Protocol/CpuInfo/CpuInfo.h b/ReferenceCode/Haswell/Protocol/CpuInfo/CpuInfo.h
new file mode 100644
index 0000000..394386f
--- /dev/null
+++ b/ReferenceCode/Haswell/Protocol/CpuInfo/CpuInfo.h
@@ -0,0 +1,79 @@
+/** @file
+ Protocol used to report CPU information
+
+@copyright
+ Copyright (c) 1999 - 2014 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 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
+**/
+#ifndef _CPU_INFO_H_
+#define _CPU_INFO_H_
+
+EFI_FORWARD_DECLARATION (DXE_CPU_INFO_PROTOCOL_GUID);
+#define DXE_CPU_INFO_PROTOCOL_GUID \
+ { \
+ 0xe223cf65, 0xf6ce, 0x4122, 0xb3, 0xaf, 0x4b, 0xd1, 0x8a, 0xff, 0x40, 0xa1 \
+ }
+
+///
+/// Protocol revision number
+/// Any backwards compatible changes to this protocol will result in an update in the revision number
+/// Major changes will require publication of a new protocol
+///
+#define DXE_CPU_INFO_REVISION_1 1
+
+///
+/// RCVersion[7:0] is the release number.
+/// For example:
+/// Version 0.7.1 should be 00 07 01 00 (0x00070100)
+///
+#define CPU_RC_VERSION 0x01090000
+
+extern EFI_GUID gDxeCpuInfoProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _DXE_CPU_INFO_PROTOCOL DXE_CPU_INFO_PROTOCOL;
+
+//
+// CPU Common Feature Definition
+//
+
+///
+/// The processor Command Feature Definition is a super set and abstracts from hardware.
+///
+#define TXT_SUPPORT 1
+#define VMX_SUPPORT (1 << 1)
+#define XD_SUPPORT (1 << 2)
+#define DCA_SUPPORT (1 << 3)
+#define XAPIC_SUPPORT (1 << 4)
+#define AES_SUPPORT (1 << 5)
+#define HT_SUPPORT (1 << 6)
+#define DEBUG_SUPPORT (1 << 7)
+#define DEBUG_LOCK_SUPPORT (1 << 8)
+
+///
+/// Interface structure for the CPU Info Protocol
+///
+struct _DXE_CPU_INFO_PROTOCOL {
+ UINT8 Revision; ///< Revision for the protocol structure.
+ UINT32 RcVersion; ///< Processor Features information.
+ //
+ // Bit definition for functionality enable/disable
+ //
+ UINT64 CpuCommonFeatures; ///< CPU Supported Feature. Output from CPU code.
+};
+
+#endif
diff --git a/ReferenceCode/Haswell/Protocol/CpuPlatformPolicy/CpuPlatformPolicy.c b/ReferenceCode/Haswell/Protocol/CpuPlatformPolicy/CpuPlatformPolicy.c
new file mode 100644
index 0000000..906c2e5
--- /dev/null
+++ b/ReferenceCode/Haswell/Protocol/CpuPlatformPolicy/CpuPlatformPolicy.c
@@ -0,0 +1,26 @@
+/** @file
+ Protocol used for specifying platform related CPU information and policy setting.
+
+@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 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
+**/
+#include "Tiano.h"
+#include EFI_PROTOCOL_DEFINITION (CpuPlatformPolicy)
+
+EFI_GUID gDxeCpuPlatformPolicyProtocolGuid = DXE_CPU_PLATFORM_POLICY_PROTOCOL_GUID;
+
+EFI_GUID_STRING
+ (&gDxeCpuPlatformPolicyProtocolGuid, "CPU Platform Policy", "Platform related CPU information and policy settings");
diff --git a/ReferenceCode/Haswell/Protocol/CpuPlatformPolicy/CpuPlatformPolicy.h b/ReferenceCode/Haswell/Protocol/CpuPlatformPolicy/CpuPlatformPolicy.h
new file mode 100644
index 0000000..37fe5a1
--- /dev/null
+++ b/ReferenceCode/Haswell/Protocol/CpuPlatformPolicy/CpuPlatformPolicy.h
@@ -0,0 +1,329 @@
+/** @file
+ Protocol used for specifying platform related CPU information and policy setting.
+
+@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 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
+**/
+#ifndef _CPU_PLATFORM_POLICY_H_
+#define _CPU_PLATFORM_POLICY_H_
+
+#include "CpuPmConfig.h"
+
+#include EFI_PROTOCOL_DEFINITION (MpService)
+#include EFI_GUID_DEFINITION (DataHubRecords)
+
+#if (EFI_SPECIFICATION_VERSION >= 0x2000A)
+#include EFI_PROTOCOL_DEFINITION (HiiDatabase)
+#else
+#include EFI_PROTOCOL_DEFINITION (Hii)
+#endif
+
+EFI_FORWARD_DECLARATION (DXE_CPU_PLATFORM_POLICY_PROTOCOL_GUID);
+#define DXE_CPU_PLATFORM_POLICY_PROTOCOL_GUID \
+ { \
+ 0x1279e288, 0x24cd, 0x47e9, 0x96, 0xba, 0xd7, 0xa3, 0x8c, 0x17, 0xbd, 0x64 \
+ }
+
+///
+/// Protocol revision number
+/// Any backwards compatible changes to this protocol will result in an update in the revision number
+/// Major changes will require publication of a new protocol
+///
+
+///
+/// Revision 1: Initial version
+///
+#define DXE_PLATFORM_CPU_POLICY_PROTOCOL_REVISION_1 1
+///
+/// Revision 2: Added CPU_CONFIG.DebugInterfaceEnable
+/// Added CPU_CONFIG.DebugInterfaceLockEnable
+///
+#define DXE_PLATFORM_CPU_POLICY_PROTOCOL_REVISION_2 2
+///
+/// Revision 3: Added CPU_CONFIG.ApIdleManner
+/// Added CPU_CONFIG.ApHandoffManner
+///
+#define DXE_PLATFORM_CPU_POLICY_PROTOCOL_REVISION_3 3
+
+///
+/// Revision 4: Added POWER_MGMT_CONFIG.THERM_FUNCTION_ENABLES.Pl1ThermalControl
+///
+#define DXE_PLATFORM_CPU_POLICY_PROTOCOL_REVISION_4 4
+///
+/// Revision 5: Added POWER_MGMT_CONFIG.PPM_TURBO_SETTINGS.PowerLimit3
+/// POWER_MGMT_CONFIG.PPM_TURBO_SETTINGS.PowerLimit3Time
+/// POWER_MGMT_CONFIG.PPM_TURBO_SETTINGS.PowerLimit3DutyCycle
+/// POWER_MGMT_CONFIG.PPM_TURBO_SETTINGS.PowerLimit3Lock
+///
+#define DXE_PLATFORM_CPU_POLICY_PROTOCOL_REVISION_5 5
+
+///
+/// Revision 6: Added POWER_MGMT_CONFIG.CustomPowerUnit .Support for user to configuration custom Power Limts in milli watts
+/// Default Power Unit for follwing Items changes to MilliWatts
+/// POWER_MGMT_CONFIG.PPM_TURBO_SETTINGS
+/// PowerLimit1
+/// PowerLimit2
+/// PowerLimit3
+/// POWER_MGMT_CONFIG.PPM_CUSTOM_CTDP
+/// CustomPowerLimit1
+/// CustomPowerLimit2
+///
+///
+
+#define DXE_PLATFORM_CPU_POLICY_PROTOCOL_REVISION_6 6
+
+///
+/// Revision 7: Added POWER_MGMT_CONFIG.THERM_FUNCTION_ENABLES.Pl1ThermalControlFloor. Changed definition of
+/// POWER_MGMT_CONFIG.THERM_FUNCTION_ENABLES.Pl1ThermalControl from 1 (enable) to 1 (enable/manual)
+/// POWER_MGMT_CONFIG.THERM_FUNCTION_ENABLES.Pl1ThermalControlFloor
+///
+
+#define DXE_PLATFORM_CPU_POLICY_PROTOCOL_REVISION_7 7
+
+
+extern EFI_GUID gDxeCpuPlatformPolicyProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _DXE_CPU_PLATFORM_POLICY_PROTOCOL DXE_CPU_PLATFORM_POLICY_PROTOCOL;
+
+//
+// Prototypes for the Platform CPU Protocol
+//
+
+///
+/// This function is for platform code to provide Microcode location since different BIOS has different flash layout.
+/// Platform code need to provide a function for CPU code to call to get the Microcode location in flash or memory.
+///
+typedef
+EFI_STATUS
+(EFIAPI *PLATFORM_CPU_RETRIEVE_MICROCODE)(
+ IN DXE_CPU_PLATFORM_POLICY_PROTOCOL *This,
+ OUT UINT8 **MicrocodeData
+ );
+
+typedef struct {
+ UINT32 Package;
+ UINT32 Die;
+ UINT32 Core;
+ UINT32 Thread;
+} CPU_PHYSICAL_LOCATION;
+
+///
+/// The platform category, Server, Desktop and Mobile are defined.
+///
+typedef enum {
+ CpuPlatformUnknown= 0,
+ CpuPlatformDesktop,
+ CpuPlatformMobile,
+ CpuPlatformServer,
+ CpuPlatformMax
+} CPU_PLATFORM_CATEGORY;
+
+///
+/// The reason for changing the state of the processor Only applies to Disabling processors.
+/// In future, we can add add/remove support
+///
+#define CPU_CAUSE_NOT_DISABLED 0x0000
+#define CPU_CAUSE_INTERNAL_ERROR 0x0001
+#define CPU_CAUSE_THERMAL_ERROR 0x0002
+#define CPU_CAUSE_SELFTEST_FAILURE 0x0004
+#define CPU_CAUSE_PREBOOT_TIMEOUT 0x0008
+#define CPU_CAUSE_FAILED_TO_START 0x0010
+#define CPU_CAUSE_CONFIG_ERROR 0x0020
+#define CPU_CAUSE_USER_SELECTION 0x0080
+#define CPU_CAUSE_BY_ASSOCIATION 0x0100
+#define CPU_CAUSE_UNSPECIFIED 0x8000
+
+typedef UINT32 CPU_STATE_CHANGE_CAUSE;
+
+typedef struct {
+ EFI_MP_PROC_CONTEXT *Context;
+ EFI_EXP_BASE10_DATA CoreFreq;
+ EFI_EXP_BASE10_DATA BusFreq;
+ EFI_EXP_BASE2_DATA CacheSize[EFI_CACHE_LMAX];
+ EFI_PROCESSOR_ID_DATA CpuId;
+ EFI_PROCESSOR_MICROCODE_REVISION_DATA MuData;
+ EFI_PROCESSOR_STATUS_DATA Status;
+} EFI_DETAILED_CPU_INFO;
+
+///
+/// Platform Specific Processor Information
+///
+typedef struct {
+ UINT64 ApicID; ///< APIC ID
+ STRING_REF ReferenceString; ///< Reference String
+ EFI_PROCESSOR_SOCKET_TYPE_DATA SocketType; ///< Socket Type
+ EFI_PROCESSOR_SOCKET_NAME_DATA SocketName; ///< Socket Name
+ EFI_PROCESSOR_MAX_CORE_FREQUENCY_DATA MaxCoreFrequency; ///< Maximum Core Frequency
+ EFI_PROCESSOR_MAX_FSB_FREQUENCY_DATA MaxFsbFrequency; ///< Maximum FSB Frequency
+ EFI_PROCESSOR_CORE_FREQUENCY_LIST_DATA PlatformCoreFrequencyList; ///< Platform Core Frequency List
+ EFI_PROCESSOR_FSB_FREQUENCY_LIST_DATA PlatformFsbFrequencyList; ///< Platform FSB Frequency List
+ STRING_REF AssetTag; ///< Asset Tag
+ EFI_HII_HANDLE StringHandle; ///< String Handle
+ STRING_REF SerialNumber; ///< Serial Number
+ STRING_REF PartNumber; ///< Part Number
+} PLATFORM_CPU_INFORMATION;
+
+///
+/// This interface is for platform to provide processor support layout, such as how many packages we want
+/// processor code to support. If return EFI_UNSUPPORTED, processor code will assume MAXIMUM_CPU_NUMBER and
+/// allocate MAX memory for all APs.
+///
+typedef
+EFI_STATUS
+(EFIAPI *PLATFORM_CPU_GET_MAX_COUNT)(
+ IN DXE_CPU_PLATFORM_POLICY_PROTOCOL *This,
+ OUT UINT32 *MaxThreadsPerCore,
+ OUT UINT32 *MaxCoresPerDie,
+ OUT UINT32 *MaxDiesPerPackage,
+ OUT UINT32 *MaxPackages
+ );
+
+///
+/// Platform code can provide platform specific processor information, such as processor socket Name on board,
+/// processor Socket Type, and so on for SMBIOS table creation.
+///
+typedef
+EFI_STATUS
+(EFIAPI *PLATFORM_CPU_GET_CPU_INFO)(
+ IN DXE_CPU_PLATFORM_POLICY_PROTOCOL *This,
+ IN CPU_PHYSICAL_LOCATION *Location,
+ IN OUT PLATFORM_CPU_INFORMATION *PlatformCpuInfo
+ );
+
+//
+// Generic definitions for device enabling/disabling used by CPU code
+//
+#define CPU_FEATURE_ENABLE 1
+#define CPU_FEATURE_DISABLE 0
+
+//
+// Generic definitions for DTS
+//
+#define DTS_OUT_OF_SPEC_ONLY 2
+#define DTS_OUT_OF_SPEC_OCCURRED 3
+
+///
+/// General CPU feature Configuration for all processor features enabling bit definitions are in this field.
+/// Platform code can enable/disable features thru this field.
+///
+typedef struct {
+ //
+ // Byte 0, bit definition for functionality enable/disable
+ //
+ UINT8 HtState : 1; ///< Enable or Disable Hyper Threading State; 0: Disable; 1: Enable
+ UINT8 LimitCpuidMaximumValue : 1; ///< Enable or Disable Limit Cpuid Maximum Value; 0: Disable; 1: Enable
+ UINT8 DcaState : 1; ///< @deprecated Deprecated for Client (Server specific)
+ UINT8 ExecuteDisableBit : 1; ///< Enable or Disable Execute Disable Bit; 0: Disable; 1: Enable
+ UINT8 VmxEnable : 1; ///< Enable or Disable VMX; 0: Disable; 1: Enable
+ UINT8 SmxEnable : 1; ///< Enable or Disable SMX; 0: Disable; 1: Enable
+ UINT8 FastString : 1; ///< @deprecated
+ UINT8 MachineCheckEnable : 1; ///< Enable or Disable Machine Check; 0: Disable; 1: Enable
+ //
+ // Byte 1, bit definition for functionality enable/disable
+ //
+ UINT8 MonitorMwaitEnable : 1; ///< Enable or Disable Monitor Mwait mode; 0: Disable; 1: Enable
+ UINT8 XapicEnable : 1; ///< Enable or Disable Xapic mode; 0: Disable; 1: Enable
+ UINT8 MachineCheckStatusClean : 1; ///< @deprecated
+ UINT8 IsColdReset : 1; ///< Check if is Cold Reset; 0: Not Cold Reset; 1: Cold Reset
+ UINT8 MlcStreamerPrefetcher : 1; ///< Enable or Disable MlcStreamerPrefetcher; 0: Disable; 1: Enable
+ UINT8 MlcSpatialPrefetcher : 1; ///< Enable or Disable MlcSpatialPrefetcher; 0: Disable; 1: Enable
+ UINT8 EnableDts : 2; ///< Enable or Disable DTS feature; 0=Disable; 1=Enable; 2=OUT_OF_SPEC;
+ //
+ // Byte 2, byte definition for addiional functionalities expected later
+ //
+ UINT8 FviReport : 1; ///< Enable or Disable FVI report; 0: Disable; 1: Enable
+ UINT8 AesEnable : 1; ///< Enable or Disable AES feature; 0: Disable; 1: Enable
+ UINT8 DebugInterfaceEnable : 1; ///< Enable or Disable Debug Interface; This policy must be disabled for production BIOS. <b>0: Disable</b>; 1: Enable
+ UINT8 DebugInterfaceLockEnable : 1; ///< Enable or Disable Debug Interface Lock; This policy must be enabled on production platforms. 0: Disable; <b>1: Enable</b>
+ UINT8 ApIdleManner : 2; ///< Settings for AP Threads Idle; 1: HALT 2:MWAIT 3:RUN
+ UINT8 ApHandoffManner : 2; ///< Settings for AP Handoff to OS; 1: HALT 2:MWAIT32
+ //
+ // CPU feature configuration
+ //
+ UINT8 BspSelection; ///< Select BSP
+ UINT32 DcaPrefetchDelayValue; ///< @deprecated Deprecated for Client (Server specific)
+ UINT8 VirtualWireMode; ///< @deprecated
+ UINT8 SmmbaseSwSmiNumber; ///< SW SMI Number from Smbase.
+ //
+ // CPU Misc Config
+ //
+ UINT8 FviSmbiosType; ///< Create SMBIOS Table Type for FVI
+ //
+ // Functions provided by platform code
+ //
+ ///
+ /// Platform code can provide microcode location thru this function.
+ ///
+ PLATFORM_CPU_RETRIEVE_MICROCODE RetrieveMicrocode;
+ ///
+ /// Platform to provide the processor detail about Max Thread per Core, Max Cores per Die, Max Dies per
+ /// Package and Max packages.
+ ///
+ PLATFORM_CPU_GET_MAX_COUNT GetMaxCount;
+ ///
+ /// Platform code to provide platform specific processor information
+ ///
+ PLATFORM_CPU_GET_CPU_INFO GetCpuInfo;
+} CPU_CONFIG;
+
+///
+/// TxT Platform Configuration
+///
+typedef struct {
+ UINT8 ResetAux : 1; ///< Reset Auxiliary content when it is set "TRUE"
+ UINT8 Reserved : 7; ///< Reserved for future use
+ UINT8 ByetReserved[1]; ///< Reserved for future use
+} TXT_FUNCTION_CONFIG;
+
+
+///
+/// All processor security features enabling definitions are in this field.
+/// Platform code can enable/disable features thru this field.
+///
+typedef struct {
+ TXT_FUNCTION_CONFIG *TxtFunctionConfig;
+} SECURITY_CONFIG;
+
+///
+/// The CPU platform policy protocol allows the platform code to publish a set of configuration information that the
+/// CPU drivers will use to configure the processor. Platform code needs to provide the information for processor
+/// drivers to finish the initialization.
+///
+typedef struct _DXE_CPU_PLATFORM_POLICY_PROTOCOL {
+ ///
+ /// This member specifies the revision of the CPU Policy protocol. This field is used to indicate backwards
+ /// compatible changes to the protocol. Platform code that produces this protocol must fill with the correct revision
+ /// value for the PCH reference code to correctly interpret the content of the protocol fields.
+ ///
+ UINT8 Revision;
+ ///
+ /// Processor standard features configuration.
+ ///
+ CPU_CONFIG *CpuConfig;
+ ///
+ /// Processor power management features configuration.
+ ///
+ POWER_MGMT_CONFIG *PowerMgmtConfig;
+ ///
+ /// Processor security features configuration.
+ ///
+ SECURITY_CONFIG *SecurityConfig;
+} DXE_CPU_PLATFORM_POLICY_PROTOCOL;
+
+#endif
diff --git a/ReferenceCode/Haswell/Protocol/CpuPlatformPolicy/CpuPmConfig.h b/ReferenceCode/Haswell/Protocol/CpuPlatformPolicy/CpuPmConfig.h
new file mode 100644
index 0000000..d84ccab
--- /dev/null
+++ b/ReferenceCode/Haswell/Protocol/CpuPlatformPolicy/CpuPmConfig.h
@@ -0,0 +1,302 @@
+/** @file
+ Describes the defintions / functions visible to the rest of the PPM.
+
+@copyright
+ Copyright (c) 2011 - 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 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
+**/
+#ifndef _CPU_PM_CONFIG_H_
+#define _CPU_PM_CONFIG_H_
+
+///
+/// Define maximum number of custom ratio states supported
+///
+#define MAX_CUSTOM_RATIO_TABLE_ENTRIES 16
+
+///
+/// Define maximum number of custom ConfigTdp entries supported
+///
+#define MAX_CUSTOM_CTDP_ENTRIES 3
+
+///
+/// This structure is used to describe the custom processor ratio table desired by the platform
+///
+typedef struct {
+ ///
+ /// The number of custom ratio state entries, it must be a value from 2 to 16 for a valid custom ratio table.
+ ///
+ UINT8 NumberOfEntries;
+ UINT32 Cpuid; ///< The CPU ID for which this custom ratio table applies.
+ UINT16 MaxRatio; ///< The maximum ratio of the custom ratio table.
+ UINT16 StateRatio[MAX_CUSTOM_RATIO_TABLE_ENTRIES]; ///< The processor ratios in the custom ratio table.
+} PPM_CUSTOM_RATIO_TABLE;
+
+///
+/// This structure is used to describe which of the PPM functions will be enabled by PPM implementation.
+///
+typedef struct {
+ UINT32 Eist : 1; ///< Enable or Disable Intel SpeedStep Technology.
+ UINT32 Cx : 1; ///< Enable or Disable CPU power states (C-states).
+ UINT32 C1e : 1; ///< Enable or Disable Enhanced C-states.
+ UINT32 C3 : 1; ///< Enable or Disable C3.
+ UINT32 C6 : 1; ///< Enable or Disable C6.
+ UINT32 DeepCState : 3; ///< Enable or Disable C7/C7S.
+ UINT32 LongLatencyC6 : 1; ///< Enable or Disable C6 Long Latency.
+ UINT32 LongLatencyC7 : 1; ///< Enable or Disable C7 Long Latency.
+ UINT32 C8 : 1; ///< Enable or Disable C8.
+ UINT32 C9 : 1; ///< Enable or Disable C9.
+ UINT32 C10 : 1; ///< Enable or Disable C10.
+ UINT32 C1AutoDemotion : 1; ///< Enable or Disable C1 Auto Demotion.
+ UINT32 C3AutoDemotion : 1; ///< Enable or Disable C3 Auto Demotion.
+ UINT32 TurboMode : 1; ///< Enable or Disable long duration Turbo Mode.
+ UINT32 PowerLimit2 : 1; ///< Enable or Disable short duration Turbo Mode.
+ UINT32 EnergyEfficientPState : 1; ///< Enable or Disable Energy Efficient P-state will be applied in Turbo mode.
+ UINT32 BiProcHot : 1; ///< @deprecated in Powermgmt policy and moved to THERM_FUNCTION_ENABLES.
+ UINT32 TStates : 1; ///< @deprecated in Powermgmt policy and moved to THERM_FUNCTION_ENABLES.
+ UINT32 Xe : 1; ///< Enable or Disable Intel Extreme Edition support.
+ UINT32 C1UnDemotion : 1; ///< Enable or Disable C1UnDemotion.
+ UINT32 C3UnDemotion : 1; ///< Enable or Disable C3UnDemotion.
+ UINT32 PkgCStateDemotion : 1; ///< Enable or Disable Package Cstate Demotion.
+ UINT32 PkgCStateUnDemotion : 1; ///< Enable or Disable Package Cstate UnDemotion.
+ UINT32 DisableProcHotOut : 1; ///< @deprecated in Powermgmt policy and moved to THERM_FUNCTION_ENABLES.
+ UINT32 DisableVRThermalAlert : 1; ///< @deprecated in Powermgmt policy and moved to THERM_FUNCTION_ENABLES.
+ UINT32 ProcHotResponce : 1; ///< @deprecated in Powermgmt policy and moved to THERM_FUNCTION_ENABLES.
+ UINT32 AutoThermalReporting : 1; ///< @deprecated in Powermgmt policy and moved to THERM_FUNCTION_ENABLES.
+ UINT32 CStatePreWake : 1; ///< Enable or Disable CState-Pre wake.
+ UINT32 ThermalMonitor : 1; ///< @deprecated in Powermgmt policy and moved to THERM_FUNCTION_ENABLES.
+ UINT32 LakeTiny : 1; ///< Enable or Disable LakeTiny Support.
+ UINT32 TimedMwait : 1; ///< Enable or Disable TimedMwait Support.
+ UINT32 Reserved : 2; ///< Bits reserved for future use.
+} PPM_FUNCTION_ENABLES;
+
+///
+/// This structure is used to describe various PPM turbo settings
+///
+typedef struct _PPM_TURBO_SETTINGS {
+ UINT16 PowerLimit1; ///< Package Long duration turbo mode power limit in 125mw or watts.
+ UINT32 PowerLimit1Time; ///< Package Long duration turbo mode time window in seconds.
+ UINT16 PowerLimit2; ///< Package Short duration turbo mode power limit in 125mw or watts.
+ ///
+ /// Describes whether TURBO_POWER_LIMIT[63] should be set. Setting this bit will lock all Turbo settings.
+ ///
+ UINT8 TurboPowerLimitLock;
+ UINT16 DdrPowerLimit1; ///< @deprecated in Powermgmt policy
+ UINT32 DdrPowerLimit1Time; ///< @deprecated in Powermgmt policy
+ UINT16 DdrPowerLimit2; ///< @deprecated in Powermgmt policy
+ UINT8 DdrPowerLimitLock; ///< @deprecated in Powermgmt policy
+ ///
+ /// Configuration for boot TDP selection, value 0 describes TDP Nominal, value 1 describes TDP Down and
+ /// value 2 describes TDP Up.
+ ///
+ UINT8 ConfigTdpLevel;
+ ///
+ /// Configurable TDP Mode Lock can be sets the to Lock ConfigTdp mode settings from runtime change.
+ ///
+ UINT8 ConfigTdpLock;
+ UINT8 ConfigTdpBios; ///< Configuration whether load Configurable TDP SSDT.
+ UINT8 EnergyPolicy; ///< Describes the Energy efficiency policy to be set in MSR 0x1B0.
+
+ //
+ // PL3 configuration
+ //
+ UINT16 PowerLimit3; ///< Package PL3 power limit in 125mw or watts.
+ UINT32 PowerLimit3Time; ///< Package PL3 time window in seconds.
+ UINT8 PowerLimit3DutyCycle; ///< Package PL3 Duty Cycle.
+ UINT8 PowerLimit3Lock; ///< Package PL3 MSR 615h lock.
+
+} PPM_TURBO_SETTINGS;
+
+///
+/// PPM Custom ConfigTdp Settings
+///
+typedef struct _PPM_CUSTOM_CTDP_TABLE {
+ UINT16 CustomPowerLimit1; ///< Short term Power Limit value for custom cTDP level in 125mw or watts.
+ UINT16 CustomPowerLimit2; ///< Long term Power Limit value for custom cTDP level in 125mw or watts.
+ UINT8 CustomPowerLimit1Time; ///< Short term Power Limit time window value for custom cTDP level.
+ UINT8 CustomTurboActivationRatio; ///< Turbo Activation Ratio for custom cTDP level.
+ UINT8 CustomConfigTdpControl; ///< Config Tdp Control (0/1/2) value for custom cTDP level.
+} PPM_CUSTOM_CTDP_TABLE;
+
+///
+/// This structure is used to configure custom ConfigTdp level settings.
+///
+typedef struct _PPM_CUSTOM_CTDP {
+ UINT8 ConfigTdpCustom; ///< Describes whether or not Custom Config Tdp should be enabled.
+ UINT8 CustomTdpCount; ///< Describes the number of Custom Config Tdp levels required (1/2/3).
+ UINT8 CustomBootModeIndex; ///< Describes the Boot mode index selection from Custom Tdp levels.Index to CustomConfigTdpTable. valid values are 0,1,2.
+ ///
+ /// Describes the details of each Custom Config Tdp levels. This supports up to MAX_CUSTOM_CTDP_ENTRIES number
+ /// of Custom ConfigTdp levels.
+ ///
+ PPM_CUSTOM_CTDP_TABLE CustomConfigTdpTable[MAX_CUSTOM_CTDP_ENTRIES];
+} PPM_CUSTOM_CTDP;
+
+///
+/// This structure is used to control enabled / disabled various PPM MSR lock settings
+///
+typedef struct _PPM_LOCK_ENABLES {
+ UINT32 PmgCstCfgCtrlLock : 1; ///< Setting this to 1 will set MSR 0xE2[15]
+ UINT32 OverclockingLock : 1; ///< Setting this to 1 will set MSR 0x194[20]
+ UINT32 ProcHotLock : 1; ///< Setting this to 1 will set MSR 0x1FC[23]
+ UINT32 Reserved : 29; ///< Bits reserved for future use.
+} PPM_LOCK_ENABLES;
+///
+/// PM Deep C State Limit
+///
+typedef enum {
+ Disabled = 0,
+ DeepC7,
+ DeepC7S
+} DEEP_C_STATE;
+///
+/// PPM Package C State Limit
+///
+typedef enum {
+ PkgC0C1 = 0,
+ PkgC2,
+ PkgC3,
+ PkgC6,
+ PkgC7,
+ PkgC7s,
+ PkgC8,
+ PkgC9,
+ PkgC10,
+ PkgCMax,
+ PkgCpuDefault = 254,
+ PkgAuto = 255
+} MAX_PKG_C_STATE;
+///
+/// PPM Package C State Time Limit
+///
+typedef enum {
+ TimeUnit1ns = 0,
+ TimeUnit32ns,
+ TimeUnit1024ns,
+ TimeUnit32768ns,
+ TimeUnit1048576ns,
+ TimeUnit33554432ns
+} C_STATE_TIME_UNIT;
+///
+/// Custom Power Uints.User can choose to enter in MilliWatts or Watts
+///
+typedef enum {
+ PowerUnitWatts = 0, ///< in Watts
+ PowerUnit125MilliWatts, ///< in 125 Milli Watts. Example 11.250 W Value to use for Power limts 90
+ PowerUnitMax
+} CUSTOM_POWER_UNIT;
+
+typedef enum {
+ Percent5 = 242,
+ Percent10 = 229,
+ Percent15 = 217,
+ Percent20 = 204,
+ Percent25 = 191,
+ Percent30 = 178,
+ Percent35 = 166,
+ Percent40 = 153,
+ Percent45 = 140,
+ Percent50 = 127,
+ Percent55 = 115,
+ Percent60 = 102,
+ Percent65 = 89,
+ Percent70 = 76,
+ Percent75 = 64,
+ Percent80 = 51,
+ Percent85 = 38,
+ Percent90 = 25,
+ Percent95 = 13,
+ Percent100 = 0
+} PL1_THERMAL_THROTTLE_FLOOR_UNIT;
+
+typedef struct {
+ PL1_THERMAL_THROTTLE_FLOOR_UNIT FloorIA; /// < FLOOR_IA, Default: 0 (Percent100)
+ PL1_THERMAL_THROTTLE_FLOOR_UNIT FloorGT; /// < FLOOR_GT, Default: 0 (Percent100)
+ PL1_THERMAL_THROTTLE_FLOOR_UNIT FloorPCH; /// < FLOOR_PCH, Default: 0 (Percent100)
+} PL1_THERMAL_CONTROL_FLOOR;
+
+///
+/// This structure is used to describe which of the Thermal functions will be enabled by Thermal implementation.
+///
+typedef struct {
+ UINT16 BiProcHot : 1; ///< Enable or Disable Bi-Directional PROCHOT#.
+ UINT16 TStates : 1; ///< Enable or Disable T states.
+ UINT16 DisableProcHotOut : 1; ///< Enable or Disable PROCHOT# signal being driven externally.
+ UINT16 DisableVRThermalAlert : 1; ///< Enable or Disable VR Thermal Alert.
+ UINT16 ProcHotResponce : 1; ///< Enable or Disable PROCHOT# Responce.
+ UINT16 AutoThermalReporting : 1; ///< Enable or Disable Thermal Reporting through ACPI tables.
+ UINT16 ThermalMonitor : 1; ///< Enable or Disable Thermal Monitor.
+ UINT16 Pl1ThermalControl : 2; ///< Disable(0), Enable/Manual(1), Auto(2) PL1 thermal throttling features
+ UINT16 ThermReserved : 7; ///< Reserved
+ PL1_THERMAL_CONTROL_FLOOR Pl1ThermalControlFloor; ///< PL1 Floor Throttle Values
+} THERM_FUNCTION_ENABLES;
+
+///
+/// Power management Configuration for all processor Power Management features enabling definitions are in this field.
+/// Platform code can enable/disable features thru this field.
+///
+typedef struct {
+ ///
+ /// This structure is used to describe which of the PPM functions should be enabled. For details of this structure,
+ /// please see Related Definitions.
+ ///
+ PPM_FUNCTION_ENABLES *pFunctionEnables;
+ ///
+ /// This structure is used to describe the custom CPU Frequency Table that should be used. For details of this
+ /// structure, please see Related Definitions.
+ ///
+ PPM_CUSTOM_RATIO_TABLE *pCustomRatioTable;
+ ///
+ /// This structure is used to describe long duration and short duration turbo settings. For details of this
+ /// structure, please see Related Definitions.
+ ///
+ PPM_TURBO_SETTINGS *pTurboSettings;
+ UINT8 S3RestoreMsrSwSmiNumber; ///< SW SMI number to restore the power Mgmt MSRs during S3 resume.
+ UINT8 *pRatioLimit; ///< This field is a pointer to Ratio Limit.
+ PPM_LOCK_ENABLES *pPpmLockEnables; ///< This field is a pointer to PPM_LOCK_ENABLES structure.
+ PPM_CUSTOM_CTDP *pCustomCtdpSettings; ///< This structure is used to describe the custom config TDP settings.
+ ///
+ /// This field is used to set the Max Pkg Cstate. Default set to Auto which limits the Max Pkg Cstate to deep C-state.
+ ///
+ MAX_PKG_C_STATE PkgCStateLimit;
+ C_STATE_TIME_UNIT CstateLatencyControl0TimeUnit; ///< TimeUnit for Latency Control0 MSR 0x60A[12:10].
+ C_STATE_TIME_UNIT CstateLatencyControl1TimeUnit; ///< TimeUnit for Latency Control1 MSR 0x60B[12:10].
+ C_STATE_TIME_UNIT CstateLatencyControl2TimeUnit; ///< TimeUnit for Latency Control2 MSR 0x60C[12:10].
+ C_STATE_TIME_UNIT CstateLatencyControl3TimeUnit; ///< TimeUnit for Latency Control3 MSR 0x633[12:10].
+ C_STATE_TIME_UNIT CstateLatencyControl4TimeUnit; ///< TimeUnit for Latency Control4 MSR 0x634[12:10].
+ C_STATE_TIME_UNIT CstateLatencyControl5TimeUnit; ///< TimeUnit for Latency Control5 MSR 0x635[12:10].
+ UINT16 CstateLatencyControl0Irtl; ///< Interrupt Response Time Limit of LatencyContol0 MSR 0x60A[9:0].
+ UINT16 CstateLatencyControl1Irtl; ///< Interrupt Response Time Limit of LatencyContol1 MSR 0x60B[9:0].
+ UINT16 CstateLatencyControl2Irtl; ///< Interrupt Response Time Limit of LatencyContol2 MSR 0x60C[9:0].
+ UINT16 CstateLatencyControl3Irtl; ///< Interrupt Response Time Limit of LatencyContol3 MSR 0x633[9:0].
+ UINT16 CstateLatencyControl4Irtl; ///< Interrupt Response Time Limit of LatencyContol4 MSR 0x634[9:0].
+ UINT16 CstateLatencyControl5Irtl; ///< Interrupt Response Time Limit of LatencyContol5 MSR 0x635[9:0].
+ BOOLEAN RfiFreqTunningOffsetIsNegative; ///< Specify RfiFreqTunningOffset is Positive or Negative.
+ UINT8 RfiFreqTunningOffset; ///< specify the Target FIVR Frequency offset.
+ ///
+ /// Calibrate 24MHz BCLK support; 0: NO_CALIBRATE, 1: PCODE_CALIBRATE, 2: BIOS_CALIBRATE (Default :1)
+ ///
+ UINT8 PcodeCalibration;
+ BOOLEAN EnableRerunPcodeCalibration; ///< Calibrate C state 24MHz BCLK support.
+ ///
+ /// This structure is used to describe which of the Thermal functions should be enabled. For details of this
+ /// structure, please see Related Definitions.
+ ///
+ THERM_FUNCTION_ENABLES *ThermalFuncEnables;
+ CUSTOM_POWER_UNIT CustomPowerUnit; ///< Power Management Custom Power Limit Unit.
+
+} POWER_MGMT_CONFIG;
+
+#endif
diff --git a/ReferenceCode/Haswell/Protocol/CpuProtocolLib.cif b/ReferenceCode/Haswell/Protocol/CpuProtocolLib.cif
new file mode 100644
index 0000000..4a25ea6
--- /dev/null
+++ b/ReferenceCode/Haswell/Protocol/CpuProtocolLib.cif
@@ -0,0 +1,27 @@
+<component>
+ name = "CpuProtocolLib"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\Protocol\"
+ RefName = "CpuProtocolLib"
+[files]
+"CpuProtocolLib.sdl"
+"CpuProtocolLib.mak"
+"CpuProtocolLib.inf"
+"CpuInfo\CpuInfo.c"
+"CpuInfo\CpuInfo.h"
+"CpuPlatformPolicy\CpuPlatformPolicy.c"
+"CpuPlatformPolicy\CpuPlatformPolicy.h"
+"CpuPlatformPolicy\CpuPmConfig.h"
+"MpService\MpService.c"
+"MpService\MpService.h"
+"Pfat\Pfat.c"
+"Pfat\Pfat.h"
+"PiMpService\PiMpService.c"
+"PiMpService\PiMpService.h"
+"PowerMgmtInitDone\PowerMgmtInitDone.c"
+"PowerMgmtInitDone\PowerMgmtInitDone.h"
+"PpmGlobalNvsArea\PpmGlobalNvsArea.c"
+"PpmGlobalNvsArea\PpmGlobalNvsArea.h"
+"SmmThunk\SmmThunk.c"
+"SmmThunk\SmmThunk.h"
+<endComponent>
diff --git a/ReferenceCode/Haswell/Protocol/CpuProtocolLib.inf b/ReferenceCode/Haswell/Protocol/CpuProtocolLib.inf
new file mode 100644
index 0000000..afd4836
--- /dev/null
+++ b/ReferenceCode/Haswell/Protocol/CpuProtocolLib.inf
@@ -0,0 +1,75 @@
+## @file
+# Component description file for the CPU protocol library
+#
+#@copyright
+# Copyright (c) 2004 - 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
+#
+
+
+[defines]
+BASE_NAME = CpuProtocolLib
+COMPONENT_TYPE = LIBRARY
+
+[sources.common]
+ MpService/MpService.c
+ MpService/MpService.h
+ CpuPlatformPolicy/CpuPlatformPolicy.c
+ CpuPlatformPolicy/CpuPlatformPolicy.h
+ SmmThunk/SmmThunk.c
+ SmmThunk/SmmThunk.h
+ CpuInfo/CpuInfo.c
+ CpuInfo/CpuInfo.h
+ PiMpService/PiMpService.c
+ PiMpService/PiMpService.h
+ Pfat/Pfat.c
+ Pfat/Pfat.h
+ PowerMgmtInitDone/PowerMgmtInitDone.h
+ PowerMgmtInitDone/PowerMgmtInitDone.c
+ PpmGlobalNvsArea/PpmGlobalNvsArea.h
+ PpmGlobalNvsArea/PpmGlobalNvsArea.c
+
+[includes.common]
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)
+#
+# Typically the sample code referenced will be available in the code base already
+# So keep this include at the end to defer to the source base definition
+# and only use the sample code definition if source base does not include these files.
+#
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/SampleCode
+
+#
+# Edk II Glue Library, some hearder are included by R9 header so have to include
+#
+
+ $(EFI_SOURCE)
+ $(EFI_SOURCE)/Framework
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+
+[nmake.common]
+C_STD_INCLUDE=
diff --git a/ReferenceCode/Haswell/Protocol/CpuProtocolLib.mak b/ReferenceCode/Haswell/Protocol/CpuProtocolLib.mak
new file mode 100644
index 0000000..e83e201
--- /dev/null
+++ b/ReferenceCode/Haswell/Protocol/CpuProtocolLib.mak
@@ -0,0 +1,28 @@
+# MAK file for the ModulePart:PpmProtocolLib
+
+all : CpuProtocolLib
+
+$(BUILD_DIR)\CpuProtocolLib.lib : CpuProtocolLib
+
+CpuProtocolLib : $(BUILD_DIR)\CpuProtocolLib.mak CpuProtocolLibBin
+
+$(BUILD_DIR)\CpuProtocolLib.mak : $(CpuProtocolLib_DIR)\$(@B).cif $(CpuProtocolLib_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(CpuProtocolLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+
+CpuProtocolLibDxe_DEFINES = \
+ $(CFLAGS) \
+!IF "$(x64_BUILD)"=="1"
+ /DMDE_CPU_X64 \
+!ELSE
+ /DMDE_CPU_IA32 \
+!ENDIF
+
+
+CpuProtocolLibBin :
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\CpuProtocolLib.mak all\
+ "MY_INCLUDES=$(EDK_INCLUDES) $(PROJECT_CPU_INCLUDES) $(EdkIIGlueLib_INCLUDES)" \
+ "CFLAGS=$(CpuProtocolLibDxe_DEFINES)"\
+ TYPE=LIBRARY \
+ LIBRARY_NAME=$(CpuProtocolLib_LIB)
diff --git a/ReferenceCode/Haswell/Protocol/CpuProtocolLib.sdl b/ReferenceCode/Haswell/Protocol/CpuProtocolLib.sdl
new file mode 100644
index 0000000..7fb311c
--- /dev/null
+++ b/ReferenceCode/Haswell/Protocol/CpuProtocolLib.sdl
@@ -0,0 +1,29 @@
+TOKEN
+ Name = CpuProtocolLib_SUPPORT
+ Value = "1"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+ Help = "Main switch to enable CpuProtocolLib support in Project"
+End
+
+MODULE
+ Help = "Includes CpuProtocolLib.mak to Project"
+ File = "CpuProtocolLib.mak"
+End
+
+PATH
+ Name = "CpuProtocolLib_DIR"
+End
+
+ELINK
+ Name = "CpuProtocolLib_LIB"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\CpuProtocolLib.lib"
+ Parent = "CpuProtocolLib_LIB"
+ InvokeOrder = AfterParent
+End
diff --git a/ReferenceCode/Haswell/Protocol/MpService/MpService.c b/ReferenceCode/Haswell/Protocol/MpService/MpService.c
new file mode 100644
index 0000000..bf3c0c2
--- /dev/null
+++ b/ReferenceCode/Haswell/Protocol/MpService/MpService.c
@@ -0,0 +1,24 @@
+/** @file
+ This is a protocol produced by the MP DXE driver.
+
+@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 'Framework Code' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may not be modified, except as allowed by
+ additional terms of your license agreement.
+**/
+#include "Tiano.h"
+#include EFI_PROTOCOL_DEFINITION (MpService)
+
+EFI_GUID gEfiMpServiceProtocolGuid = EFI_MP_SERVICES_PROTOCOL_GUID;
+
+EFI_GUID_STRING(&gEfiMpServiceProtocolGuid, "MP SERVICE", "MP Service Protocol");
diff --git a/ReferenceCode/Haswell/Protocol/MpService/MpService.h b/ReferenceCode/Haswell/Protocol/MpService/MpService.h
new file mode 100644
index 0000000..03d3d2a
--- /dev/null
+++ b/ReferenceCode/Haswell/Protocol/MpService/MpService.h
@@ -0,0 +1,216 @@
+/** @file
+ This protocol produces MP Protocol
+
+@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 'Framework Code' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may not be modified, except as allowed by
+ additional terms of your license agreement.
+**/
+#ifndef _MP_H_
+#define _MP_H_
+
+#include "LinkedList.h"
+
+#include EFI_PROTOCOL_CONSUMER(SmmBase) // added for EFI_AP_PROCEDURE
+
+#include EFI_PROTOCOL_CONSUMER (CpuIo)
+
+#define EFI_MP_SERVICES_PROTOCOL_GUID \
+ { \
+ 0xf33261e7, 0x23cb, 0x11d5, 0xbd, 0x5c, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 \
+ }
+
+EFI_FORWARD_DECLARATION (EFI_MP_SERVICES_PROTOCOL);
+
+#ifndef DELIVERY_MODE_FIXED
+#define DELIVERY_MODE_FIXED 0x0
+#define DELIVERY_MODE_LOWEST_PRIORITY 0x1
+#define DELIVERY_MODE_SMI 0x2
+#define DELIVERY_MODE_REMOTE_READ 0x3
+#define DELIVERY_MODE_NMI 0x4
+#define DELIVERY_MODE_INIT 0x5
+#define DELIVERY_MODE_SIPI 0x6
+#define DELIVERY_MODE_MAX 0x7
+
+#define TRIGGER_MODE_EDGE 0x0
+#define TRIGGER_MODE_LEVEL 0x1
+#endif
+
+typedef union {
+ struct {
+ UINT32 Status : 2;
+ UINT32 Tested : 1;
+ UINT32 Reserved1 : 13;
+ UINT32 VirtualMemoryUnavailable : 1;
+ UINT32 Ia32ExecutionUnavailable : 1;
+ UINT32 FloatingPointUnavailable : 1;
+ UINT32 MiscFeaturesUnavailable : 1;
+ UINT32 Reserved2 : 12;
+ } Bits;
+ UINT32 Uint32;
+} EFI_MP_HEALTH_FLAGS;
+
+#define EFI_MP_HEALTH_FLAGS_STATUS_HEALTHY 0x0
+#define EFI_MP_HEALTH_FLAGS_STATUS_PERFORMANCE_RESTRICTED 0x1
+#define EFI_MP_HEALTH_FLAGS_STATUS_FUNCTIONALLY_RESTRICTED 0x2
+
+typedef struct {
+ EFI_MP_HEALTH_FLAGS Flags;
+ UINT32 TestStatus;
+} EFI_MP_HEALTH;
+
+typedef enum {
+ EfiCpuAP = 0,
+ EfiCpuBSP,
+ EfiCpuDesignationMaximum
+} EFI_CPU_DESIGNATION;
+
+typedef struct {
+ UINT32 Package;
+ UINT32 Die;
+ UINT32 Core;
+ UINT32 Thread;
+} PHYSICAL_LOCATION;
+
+typedef struct {
+ UINT32 ApicID;
+ BOOLEAN Enabled;
+ EFI_CPU_DESIGNATION Designation;
+ EFI_MP_HEALTH Health;
+ UINTN PackageNumber;
+ UINTN NumberOfCores;
+ UINTN NumberOfThreads;
+ UINT64 ProcessorPALCompatibilityFlags;
+ UINT64 ProcessorTestMask;
+} EFI_MP_PROC_CONTEXT;
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_MP_SERVICES_GET_GENERAL_MP_INFO)(
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ OUT UINTN *NumberOfCPUs,
+ OUT UINTN *MaximumNumberOfCPUs,
+ OUT UINTN *NumberOfEnabledCPUs,
+ OUT UINTN *RendezvousIntNumber,
+ OUT UINTN *RendezvousProcLength
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_MP_SERVICES_GET_PROCESSOR_CONTEXT)(
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ IN OUT UINTN *BufferLength,
+ IN OUT EFI_MP_PROC_CONTEXT *ProcessorContextBuffer
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_MP_SERVICES_STARTUP_ALL_APS)(
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN BOOLEAN SingleThread,
+ IN EFI_EVENT WaitEvent OPTIONAL,
+ IN UINTN TimeoutInMicroSecs OPTIONAL,
+ IN OUT VOID *ProcArguments OPTIONAL,
+ OUT UINTN *FailedCPUList OPTIONAL
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_MP_SERVICES_STARTUP_THIS_AP)(
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN UINTN ProcessorNumber,
+ IN EFI_EVENT WaitEvent OPTIONAL,
+ IN UINTN TimeoutInMicroSecs OPTIONAL,
+ IN OUT VOID *ProcArguments OPTIONAL
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_MP_SERVICES_SWITCH_BSP)(
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ IN BOOLEAN EnableOldBSP
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_MP_SERVICES_SEND_IPI)(
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ IN UINTN VectorNumber,
+ IN UINTN DeliveryMode
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_MP_SERVICES_ENABLEDISABLEAP)(
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ IN BOOLEAN NewAPState,
+ IN EFI_MP_HEALTH *HealthState
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_MP_SERVICES_WHOAMI)(
+ IN EFI_MP_SERVICES_PROTOCOL *This,
+ OUT UINTN *ProcessorNumber
+ );
+
+///
+/// This information is basically from Intel Platform Innovation Framework for EFI Multiprocessor Services Protocol
+/// Specification. When installed, the MP Services Protocol produces a collection of services that are needed for MP
+/// management, such as initialization and management of application processors.
+///
+struct _EFI_MP_SERVICES_PROTOCOL {
+ ///
+ /// This service retrieves general information of multiprocessors in the system.
+ ///
+ EFI_MP_SERVICES_GET_GENERAL_MP_INFO GetGeneralMPInfo;
+ ///
+ /// This service gets detailed MP-related information of the requested processor.
+ ///
+ EFI_MP_SERVICES_GET_PROCESSOR_CONTEXT GetProcessorContext;
+ ///
+ /// This function is used to dispatch all enabled APs to the function specified by Procedure.
+ ///
+ EFI_MP_SERVICES_STARTUP_ALL_APS StartupAllAPs;
+ ///
+ /// This function is used to dispatch one enabled AP to the function provided by the caller.
+ ///
+ EFI_MP_SERVICES_STARTUP_THIS_AP StartupThisAP;
+ ///
+ /// This service switches the requested AP to be the BSP from that point onward.
+ ///
+ EFI_MP_SERVICES_SWITCH_BSP SwitchBSP;
+ ///
+ /// This service sends an IPI to a specified AP.
+ ///
+ EFI_MP_SERVICES_SEND_IPI SendIPI;
+ ///
+ /// This service lets the caller enable or disable an AP.
+ ///
+ EFI_MP_SERVICES_ENABLEDISABLEAP EnableDisableAP;
+ ///
+ /// This service lets the caller processor get its handle number, with which any processor in the system can be
+ /// uniquely identified.
+ ///
+ EFI_MP_SERVICES_WHOAMI WhoAmI;
+};
+
+extern EFI_GUID gEfiMpServiceProtocolGuid;
+
+#endif
diff --git a/ReferenceCode/Haswell/Protocol/Pfat/Pfat.c b/ReferenceCode/Haswell/Protocol/Pfat/Pfat.c
new file mode 100644
index 0000000..b86e1f8
--- /dev/null
+++ b/ReferenceCode/Haswell/Protocol/Pfat/Pfat.c
@@ -0,0 +1,45 @@
+/** @file
+ This file defines PFAT Abstraction Protocol
+
+@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
+**/
+
+///
+/// Statements that include other files
+///
+///
+/// External include files do NOT need to be explicitly specified in real EDKII
+/// environment
+///
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#endif
+///
+/// Include the PFAT SMM Protocol header file
+///
+#include "Pfat.h"
+
+///
+/// PFAT SMM Protocol GUID definition
+///
+EFI_GUID gSmmPfatProtocolGuid = SMM_PFAT_PROTOCOL_GUID;
+
+///
+/// PFAT SMM Protocol description
+///
+EFI_GUID_STRING(&gSmmPfatProtocolGuid, "SMM PFAT Protocol", "Intel(R) Platform Firmware Armoring Technology Protocol");
diff --git a/ReferenceCode/Haswell/Protocol/Pfat/Pfat.h b/ReferenceCode/Haswell/Protocol/Pfat/Pfat.h
new file mode 100644
index 0000000..b78905a
--- /dev/null
+++ b/ReferenceCode/Haswell/Protocol/Pfat/Pfat.h
@@ -0,0 +1,129 @@
+/** @file
+ This file defines the PFAT Protocol which implements the
+ Intel(R) PFAT Host Controller Compatibility Interface.
+
+@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 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
+**/
+#ifndef _PFAT_H_
+#define _PFAT_H_
+
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+///
+/// GUID to locate PFAT SMM Protocol
+///
+#define SMM_PFAT_PROTOCOL_GUID \
+ { \
+ 0xc3e156e4, 0x27b3, 0x4dff, 0xb8, 0x96, 0xfb, 0x11, 0x3b, 0x2e, 0x68, 0xb5 \
+ }
+#else
+///
+/// GUID to locate PFAT SMM Protocol
+///
+#define SMM_PFAT_PROTOCOL_GUID \
+ { \
+ 0xc3e156e4, 0x27b3, 0x4dff, \
+ { \
+ 0xb8, 0x96, 0xfb, 0x11, 0x3b, 0x2e, 0x68, 0xb5 \
+ } \
+ }
+#endif
+
+///
+/// Extern the GUID for protocol users.
+///
+extern EFI_GUID gSmmPfatProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _PFAT_PROTOCOL PFAT_PROTOCOL;
+
+/**
+ This service will write PFAT_DIRECTORY MSR and invoke the PFAT Module by writing to PLAT_FRMW_PROT_TRIGGER MSR for writing/erasing to flash.
+ BIOS should invoke PFAT_PROTOCOL.Write() or PFAT_PROTOCOL.Erase() function prior to calling PFAT_PROTOCOL.Execute() for flash writes/erases (except for BiosUpdate).
+ Write()/Erase() function will render PFAT script during execution.
+ Execute() function will implement the following steps:
+ 1. Update PFAT directory with address of PUP.
+ 2. All the AP's except the master thread are put to sleep.
+ 3. PFAT module is invoked from BSP to execute desired operation.
+ If BiosUpdate flag is set to true, PUP (PUP Header + PFAT Script + Update data) is part of data that is passed to SMI Handler. SMI Handler invokes PFAT module to process the update.
+ This function would be called by runtime driver, please do not use any MMIO macro here.
+
+ @param[in] This Pointer to the PFAT_PROTOCOL instance.
+ @param[in] BiosUpdate Flag to indicate flash update is requested by the Tool
+
+ @retval EFI_SUCCESS Successfully completed flash operation.
+ @retval EFI_INVALID_PARAMETER The parameters specified are not valid.
+ @retval EFI_UNSUPPORTED The CPU or SPI memory is not supported.
+ @retval EFI_DEVICE_ERROR Device error, command aborts abnormally.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PFAT_EXECUTE)(
+ IN PFAT_PROTOCOL *This,
+ IN BOOLEAN BiosUpdate
+ );
+
+/**
+ This service fills PFAT script buffer for flash writes.
+ BIOS should invoke this function prior to calling PFAT_PROTOCOL.Execute() with all the relevant data required for flash write.
+ This function will not invoke PFAT Module, only create script required for writing to flash.
+ This function would be called by runtime driver, please do not use any MMIO macro here.
+
+ @param[in] This Pointer to the PFAT_PROTOCOL instance.
+ @param[in] Address This value specifies the offset from the start of the SPI Flash component where BIOS Image is located.
+ @param[in] DataByteCount Number of bytes in the data portion.
+ @param[in] Buffer Pointer to caller-allocated buffer containing the dada sent.
+**/
+typedef
+VOID
+(EFIAPI *PFAT_WRITE)(
+ IN PFAT_PROTOCOL *This,
+ IN UINTN Address,
+ IN UINT32 DataByteCount,
+ IN OUT UINT8 *Buffer
+ );
+
+/**
+ This service fills PFAT script buffer for erasing blocks in flash.
+ BIOS should invoke this function prior to calling PFAT_PROTOCOL.Execute() with all the relevant data required for flash erase.
+ This function will not invoke PFAT module, only create script required for erasing each block in the flash.
+ This function would be called by runtime driver, please do not use any MMIO macro here.
+
+ @param[in] This Pointer to the PFAT_PROTOCOL instance.
+ @param[in] Address This value specifies the offset from the start of the SPI Flash component where BIOS Image is located.
+**/
+typedef
+VOID
+(EFIAPI *PFAT_ERASE)(
+ IN PFAT_PROTOCOL *This,
+ IN UINTN Address
+ );
+
+/**
+ This protocol provides all the services required for flash writes/erases via PFAT
+ PFAT Module can only be launched from SMM, this means that all flash writes & erases
+ that BIOS needs to do must flow thru SMI Handler and so dependency on SMM_BASE_PROTOCOL
+ for installing PFAT Protocol. Prior to PFAT SMM Protocol being installed there should
+ be no writes/erases to flash.
+**/
+struct _PFAT_PROTOCOL {
+ PFAT_WRITE Write; ///< Invoked to fill up PFAT script buffer for flash writes
+ PFAT_ERASE Erase; ///< Invoked to fill up PFAT script buffer for flash erases
+ PFAT_EXECUTE Execute; ///< Will trigger invocation of PFAT module
+};
+
+#endif
diff --git a/ReferenceCode/Haswell/Protocol/PiMpService/PiMpService.c b/ReferenceCode/Haswell/Protocol/PiMpService/PiMpService.c
new file mode 100644
index 0000000..c1a65e5
--- /dev/null
+++ b/ReferenceCode/Haswell/Protocol/PiMpService/PiMpService.c
@@ -0,0 +1,24 @@
+/** @file
+ GUID Definition for the MP Services Protocol defined in the PI 1.1 spec.
+
+@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 'Framework Code' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may not be modified, except as allowed by
+ additional terms of your license agreement.
+**/
+#include "Tiano.h"
+#include EFI_PROTOCOL_DEFINITION (PiMpService)
+
+EFI_GUID gEfiPiMpServiceProtocolGuid = EFI_PI_MP_SERVICES_PROTOCOL_GUID;
+
+EFI_GUID_STRING(&gEfiPiMpServiceProtocolGuid, "PI MP SERVICE", "PI MP Service Protocol");
diff --git a/ReferenceCode/Haswell/Protocol/PiMpService/PiMpService.h b/ReferenceCode/Haswell/Protocol/PiMpService/PiMpService.h
new file mode 100644
index 0000000..1bf33b1
--- /dev/null
+++ b/ReferenceCode/Haswell/Protocol/PiMpService/PiMpService.h
@@ -0,0 +1,500 @@
+/** @file
+ Definitions for the PI MP Services Protocol defined in the PI spec.
+
+@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 'Framework Code' and is licensed as such
+ under the terms of your license agreement with Intel or your
+ vendor. This file may not be modified, except as allowed by
+ additional terms of your license agreement.
+
+**/
+#ifndef _PI_MP_SERVICES_H_
+#define _PI_MP_SERVICES_H_
+
+///
+/// Share some definitions from Framework MP Services Protocol
+///
+#include EFI_PROTOCOL_CONSUMER (MpService)
+
+///
+/// Global ID for the EFI_PI_MP_SERVICES_PROTOCOL.
+///
+#define EFI_PI_MP_SERVICES_PROTOCOL_GUID \
+ { \
+ 0x3fdda605, 0xa76e, 0x4f46, \
+ { \
+ 0xad, 0x29, 0x12, 0xf4, 0x53, 0x1b, 0x3d, 0x08 \
+ } \
+ }
+
+///
+/// Forward declaration for the EFI_PI_MP_SERVICES_PROTOCOL.
+///
+typedef struct _EFI_PI_MP_SERVICES_PROTOCOL EFI_PI_MP_SERVICES_PROTOCOL;
+
+///
+/// Terminator for a list of failed CPUs returned by StartAllAPs().
+///
+#define END_OF_CPU_LIST 0xffffffff
+
+///
+/// This bit is used in the StatusFlag field of EFI_PROCESSOR_INFORMATION and
+/// indicates whether the processor is playing the role of BSP. If the bit is 1,
+/// then the processor is BSP. Otherwise, it is AP.
+///
+#define PROCESSOR_AS_BSP_BIT 0x00000001
+
+///
+/// This bit is used in the StatusFlag field of EFI_PROCESSOR_INFORMATION and
+/// indicates whether the processor is enabled. If the bit is 1, then the
+/// processor is enabled. Otherwise, it is disabled.
+///
+#define PROCESSOR_ENABLED_BIT 0x00000002
+
+///
+/// This bit is used in the StatusFlag field of EFI_PROCESSOR_INFORMATION and
+/// indicates whether the processor is healthy. If the bit is 1, then the
+/// processor is healthy. Otherwise, some fault has been detected for the processor.
+///
+#define PROCESSOR_HEALTH_STATUS_BIT 0x00000004
+
+///
+/// Structure that describes the pyhiscal location of a logical CPU.
+///
+typedef struct {
+ ///
+ /// Zero-based physical package number that identifies the cartridge of the processor.
+ ///
+ UINT32 Package;
+ ///
+ /// Zero-based physical core number within package of the processor.
+ ///
+ UINT32 Core;
+ ///
+ /// Zero-based logical thread number within core of the processor.
+ ///
+ UINT32 Thread;
+} EFI_CPU_PHYSICAL_LOCATION;
+
+///
+/// Structure that describes information about a logical CPU.
+///
+typedef struct {
+ ///
+ /// The unique processor ID determined by system hardware. For IA32 and X64,
+ /// the processor ID is the same as the Local APIC ID. Only the lower 8 bits
+ /// are used, and higher bits are reserved. For IPF, the lower 16 bits contains
+ /// id/eid, and higher bits are reserved.
+ ///
+ UINT64 ProcessorId;
+ ///
+ /// Flags indicating if the processor is BSP or AP, if the processor is enabled
+ /// or disabled, and if the processor is healthy. Bits 3..31 are reserved and
+ /// must be 0.
+ ///
+ /// <pre>
+ /// BSP ENABLED HEALTH Description
+ /// === ======= ====== ===================================================
+ /// 0 0 0 Unhealthy Disabled AP.
+ /// 0 0 1 Healthy Disabled AP.
+ /// 0 1 0 Unhealthy Enabled AP.
+ /// 0 1 1 Healthy Enabled AP.
+ /// 1 0 0 Invalid. The BSP can never be in the disabled state.
+ /// 1 0 1 Invalid. The BSP can never be in the disabled state.
+ /// 1 1 0 Unhealthy Enabled BSP.
+ /// 1 1 1 Healthy Enabled BSP.
+ /// </pre>
+ ///
+ UINT32 StatusFlag;
+ ///
+ /// The physical location of the processor, including the physical package number
+ /// that identifies the cartridge, the physical core number within package, and
+ /// logical thread number within core.
+ ///
+ EFI_CPU_PHYSICAL_LOCATION Location;
+} EFI_PROCESSOR_INFORMATION;
+
+/**
+ This service retrieves the number of logical processor in the platform
+ and the number of those logical processors that are enabled on this boot.
+ This service may only be called from the BSP.
+
+ This function is used to retrieve the following information:
+ - The number of logical processors that are present in the system.
+ - The number of enabled logical processors in the system at the instant
+ this call is made.
+
+ Because MP Service Protocol provides services to enable and disable processors
+ dynamically, the number of enabled logical processors may vary during the
+ course of a boot session.
+
+ If this service is called from an AP, then EFI_DEVICE_ERROR is returned.
+ If NumberOfProcessors or NumberOfEnabledProcessors is NULL, then
+ EFI_INVALID_PARAMETER is returned. Otherwise, the total number of processors
+ is returned in NumberOfProcessors, the number of currently enabled processor
+ is returned in NumberOfEnabledProcessors, and EFI_SUCCESS is returned.
+
+ @param[in] This - A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] NumberOfProcessors - Pointer to the total number of logical processors in the system,
+ including the BSP and disabled APs.
+ @param[in] NumberOfEnabledProcessors - Pointer to the number of enabled logical processors that exist
+ in system, including the BSP.
+
+ @retval EFI_SUCCESS - Number of logical processors and enabled logical processors retrieved.
+ @retval EFI_DEVICE_ERROR - Caller processor is AP.
+ @retval EFI_INVALID_PARAMETER - NumberOfProcessors is NULL.
+ @retval EFI_INVALID_PARAMETER - NumberOfEnabledProcessors is NULL.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PI_MP_SERVICES_GET_NUMBER_OF_PROCESSORS)(
+ IN EFI_PI_MP_SERVICES_PROTOCOL *This,
+ OUT UINTN *NumberOfProcessors,
+ OUT UINTN *NumberOfEnabledProcessors
+ );
+
+/**
+ Gets detailed MP-related information on the requested processor at the
+ instant this call is made. This service may only be called from the BSP.
+
+ This service retrieves detailed MP-related information about any processor
+ on the platform. Note the following:
+ - The processor information may change during the course of a boot session.
+ - The information presented here is entirely MP related.
+
+ Information regarding the number of caches and their sizes, frequency of operation,
+ slot numbers is all considered platform-related information and is not provided
+ by this service.
+
+ @param[in] This - A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] ProcessorNumber - The handle number of processor.
+ @param[in] ProcessorInfoBuffer - A pointer to the buffer where information for the requested processor is deposited.
+
+ @retval EFI_SUCCESS - Processor information successfully returned.
+ @retval EFI_DEVICE_ERROR - Caller processor is AP.
+ @retval EFI_INVALID_PARAMETER - ProcessorInfoBuffer is NULL
+ @retval EFI_NOT_FOUND - Processor with the handle specified by ProcessorNumber does not exist.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PI_MP_SERVICES_GET_PROCESSOR_INFO)(
+ IN EFI_PI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
+ );
+
+/**
+ This service executes a caller provided function on all enabled APs. APs can
+ run either simultaneously or one at a time in sequence. This service supports
+ both blocking and non-blocking requests. The non-blocking requests use EFI
+ events so the BSP can detect when the APs have finished. This service may only
+ be called from the BSP.
+
+ This function is used to dispatch all the enabled APs to the function specified
+ by Procedure. If any enabled AP is busy, then EFI_NOT_READY is returned
+ immediately and Procedure is not started on any AP.
+
+ If SingleThread is TRUE, all the enabled APs execute the function specified by
+ Procedure one by one, in ascending order of processor handle number. Otherwise,
+ all the enabled APs execute the function specified by Procedure simultaneously.
+
+ If WaitEvent is NULL, execution is in blocking mode. The BSP waits until all
+ APs finish or TimeoutInMicroSecs expires. Otherwise, execution is in non-blocking
+ mode, and the BSP returns from this service without waiting for APs. If a
+ non-blocking mode is requested after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT
+ is signaled, then EFI_UNSUPPORTED must be returned.
+
+ If the timeout specified by TimeoutInMicroseconds expires before all APs return
+ from Procedure, then Procedure on the failed APs is terminated. All enabled APs
+ are always available for further calls to EFI_PI_MP_SERVICES_PROTOCOL.StartupAllAPs()
+ and EFI_PI_MP_SERVICES_PROTOCOL.StartupThisAP(). If FailedCpuList is not NULL, its
+ content points to the list of processor handle numbers in which Procedure was
+ terminated.
+
+ Note: It is the responsibility of the consumer of the EFI_PI_MP_SERVICES_PROTOCOL.StartupAllAPs()
+ to make sure that the nature of the code that is executed on the BSP and the
+ dispatched APs is well controlled. The MP Services Protocol does not guarantee
+ that the Procedure function is MP-safe. Hence, the tasks that can be run in
+ parallel are limited to certain independent tasks and well-controlled exclusive
+ code. EFI services and protocols may not be called by APs unless otherwise
+ specified.
+
+ In blocking execution mode, BSP waits until all APs finish or
+ TimeoutInMicroSeconds expires.
+
+ In non-blocking execution mode, BSP is freed to return to the caller and then
+ proceed to the next task without having to wait for APs. The following
+ sequence needs to occur in a non-blocking execution mode:
+
+ -# The caller that intends to use this MP Services Protocol in non-blocking
+ mode creates WaitEvent by calling the EFI CreateEvent() service. The caller
+ invokes EFI_PI_MP_SERVICES_PROTOCOL.StartupAllAPs(). If the parameter WaitEvent
+ is not NULL, then StartupAllAPs() executes in non-blocking mode. It requests
+ the function specified by Procedure to be started on all the enabled APs,
+ and releases the BSP to continue with other tasks.
+ -# The caller can use the CheckEvent() and WaitForEvent() services to check
+ the state of the WaitEvent created in step 1.
+ -# When the APs complete their task or TimeoutInMicroSecondss expires, the MP
+ Service signals WaitEvent by calling the EFI SignalEvent() function. If
+ FailedCpuList is not NULL, its content is available when WaitEvent is
+ signaled. If all APs returned from Procedure prior to the timeout, then
+ FailedCpuList is set to NULL. If not all APs return from Procedure before
+ the timeout, then FailedCpuList is filled in with the list of the failed
+ APs. The buffer is allocated by MP Service Protocol using AllocatePool().
+ It is the caller's responsibility to free the buffer with FreePool() service.
+ -# This invocation of SignalEvent() function informs the caller that invoked
+ EFI_PI_MP_SERVICES_PROTOCOL.StartupAllAPs() that either all the APs completed
+ the specified task or a timeout occurred. The contents of FailedCpuList
+ can be examined to determine which APs did not complete the specified task
+ prior to the timeout.
+
+ @param[in] This - A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] Procedure - A pointer to the function to be run on enabled APs of the system.
+ @param[in] SingleThread - Indicates whether to execute the function simultaneously or one by one..
+ @param[in] WaitEvent - The event created by the caller.
+ If it is NULL, then execute in blocking mode.
+ If it is not NULL, then execute in non-blocking mode.
+ @param[in] TimeoutInMicrosecsond - The time limit in microseconds for this AP to finish the function.
+ Zero means infinity.
+ @param[in] ProcArgument - Pointer to the optional parameter of the assigned function.
+ @param[in] FailedCpuList - The list of processor numbers that fail to finish the function before
+ TimeoutInMicrosecsond expires.
+
+ @retval EFI_SUCCESS - In blocking mode, all APs have finished before the timeout expired.
+ @retval EFI_SUCCESS - In non-blocking mode, function has been dispatched to all enabled APs.
+ @retval EFI_DEVICE_ERROR - Caller processor is AP.
+ @retval EFI_NOT_STARTED - No enabled AP exists in the system.
+ @retval EFI_NOT_READY - Any enabled AP is busy.
+ @retval EFI_TIMEOUT - In blocking mode, The timeout expired before all enabled APs have finished.
+ @retval EFI_INVALID_PARAMETER - Procedure is NULL.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PI_MP_SERVICES_STARTUP_ALL_APS)(
+ IN EFI_PI_MP_SERVICES_PROTOCOL *This,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN BOOLEAN SingleThread,
+ IN EFI_EVENT WaitEvent OPTIONAL,
+ IN UINTN TimeoutInMicroSeconds,
+ IN VOID *ProcedureArgument OPTIONAL,
+ OUT UINTN **FailedCpuList OPTIONAL
+ );
+
+/**
+ This service lets the caller get one enabled AP to execute a caller-provided
+ function. The caller can request the BSP to either wait for the completion
+ of the AP or just proceed with the next task by using the EFI event mechanism.
+ See EFI_PI_MP_SERVICES_PROTOCOL.StartupAllAPs() for more details on non-blocking
+ execution support. This service may only be called from the BSP.
+
+ This function is used to dispatch one enabled AP to the function specified by
+ Procedure passing in the argument specified by ProcedureArgument. If WaitEvent
+ is NULL, execution is in blocking mode. The BSP waits until the AP finishes or
+ TimeoutInMicroSecondss expires. Otherwise, execution is in non-blocking mode.
+ BSP proceeds to the next task without waiting for the AP. If a non-blocking mode
+ is requested after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT is signaled,
+ then EFI_UNSUPPORTED must be returned.
+
+ If the timeout specified by TimeoutInMicroseconds expires before the AP returns
+ from Procedure, then execution of Procedure by the AP is terminated. The AP is
+ available for subsequent calls to EFI_PI_MP_SERVICES_PROTOCOL.StartupAllAPs() and
+ EFI_PI_MP_SERVICES_PROTOCOL.StartupThisAP().
+
+ @param[in] This - A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] Procedure - A pointer to the function to be run on the designated AP.
+ @param[in] ProcessorNumber - The handle number of AP..
+ @param[in] WaitEvent - The event created by the caller.
+ If it is NULL, then execute in blocking mode.
+ If it is not NULL, then execute in non-blocking mode.
+ @param[in] TimeoutInMicroseconds - The time limit in microseconds for this AP to finish the function.
+ Zero means infinity.
+ @param[in] ProcArgument - Pointer to the optional parameter of the assigned function.
+ @param[in] Finished - Indicates whether AP has finished assigned function.
+ In blocking mode, it is ignored.
+
+ @retval EFI_SUCCESS - In blocking mode, specified AP has finished before the timeout expires.
+ @retval EFI_SUCCESS - In non-blocking mode, function has been dispatched to specified AP.
+ @retval EFI_DEVICE_ERROR - Caller processor is AP.
+ @retval EFI_TIMEOUT - In blocking mode, the timeout expires before specified AP has finished.
+ @retval EFI_NOT_READY - Specified AP is busy.
+ @retval EFI_NOT_FOUND - Processor with the handle specified by ProcessorNumber does not exist.
+ @retval EFI_INVALID_PARAMETER - ProcessorNumber specifies the BSP or disabled AP.
+ @retval EFI_INVALID_PARAMETER - Procedure is NULL.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PI_MP_SERVICES_STARTUP_THIS_AP)(
+ IN EFI_PI_MP_SERVICES_PROTOCOL *This,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN UINTN ProcessorNumber,
+ IN EFI_EVENT WaitEvent OPTIONAL,
+ IN UINTN TimeoutInMicroseconds,
+ IN VOID *ProcedureArgument OPTIONAL,
+ OUT BOOLEAN *Finished OPTIONAL
+ );
+
+/**
+ This service switches the requested AP to be the BSP from that point onward.
+ This service changes the BSP for all purposes. This call can only be performed
+ by the current BSP.
+
+ This service switches the requested AP to be the BSP from that point onward.
+ This service changes the BSP for all purposes. The new BSP can take over the
+ execution of the old BSP and continue seamlessly from where the old one left
+ off. This service may not be supported after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT
+ is signaled.
+
+ If the BSP cannot be switched prior to the return from this service, then
+ EFI_UNSUPPORTED must be returned.
+
+ @param[in] This - A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] ProcessorNumber - The handle number of processor.
+ @param[in] EnableOldBSP - Whether to enable or disable the original BSP.
+
+ @retval EFI_SUCCESS - BSP successfully switched.
+ @retval EFI_DEVICE_ERROR - Caller processor is AP.
+ @retval EFI_NOT_FOUND - Processor with the handle specified by ProcessorNumber does not exist.
+ @retval EFI_INVALID_PARAMETER - ProcessorNumber specifies the BSP or disabled AP.
+ @retval EFI_NOT_READY - Specified AP is busy.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PI_MP_SERVICES_SWITCH_BSP)(
+ IN EFI_PI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ IN BOOLEAN EnableOldBSP
+ );
+
+/**
+ This service lets the caller enable or disable an AP from this point onward.
+ This service may only be called from the BSP.
+
+ This service allows the caller enable or disable an AP from this point onward.
+ The caller can optionally specify the health status of the AP by Health. If
+ an AP is being disabled, then the state of the disabled AP is implementation
+ dependent. If an AP is enabled, then the implementation must guarantee that a
+ complete initialization sequence is performed on the AP, so the AP is in a state
+ that is compatible with an MP operating system. This service may not be supported
+ after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT is signaled.
+
+ If the enable or disable AP operation cannot be completed prior to the return
+ from this service, then EFI_UNSUPPORTED must be returned.
+
+ @param[in] This - A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] ProcessorNumber - The handle number of processor.
+ @param[in] EnableAP - Indicates whether the newstate of the AP is enabled or disabled.
+ @param[in] HealthFlag - Indicates new health state of the AP..
+
+ @retval EFI_SUCCESS - AP successfully enabled or disabled.
+ @retval EFI_DEVICE_ERROR - Caller processor is AP.
+ @retval EFI_NOT_FOUND - Processor with the handle specified by ProcessorNumber does not exist.
+ @retval EFI_INVALID_PARAMETERS - ProcessorNumber specifies the BSP.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PI_MP_SERVICES_ENABLEDISABLEAP)(
+ IN EFI_PI_MP_SERVICES_PROTOCOL *This,
+ IN UINTN ProcessorNumber,
+ IN BOOLEAN EnableAP,
+ IN UINT32 *HealthFlag OPTIONAL
+ );
+
+/**
+ This return the handle number for the calling processor. This service may be
+ called from the BSP and APs.
+
+ This service returns the processor handle number for the calling processor.
+ The returned value is in the range from 0 to the total number of logical
+ processors minus 1. The total number of logical processors can be retrieved
+ with EFI_PI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors(). This service may be
+ called from the BSP and APs. If ProcessorNumber is NULL, then EFI_INVALID_PARAMETER
+ is returned. Otherwise, the current processors handle number is returned in
+ ProcessorNumber, and EFI_SUCCESS is returned.
+
+ @param[in] This - A pointer to the EFI_MP_SERVICES_PROTOCOL instance.
+ @param[in] ProcessorNumber - Pointer to the handle number of AP.
+
+ @retval EFI_SUCCESS - Processor number successfully returned.
+ @retval EFI_INVALID_PARAMETER - ProcessorNumber is NULL
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PI_MP_SERVICES_WHOAMI)(
+ IN EFI_PI_MP_SERVICES_PROTOCOL *This,
+ OUT UINTN *ProcessorNumber
+ );
+
+///
+/// When installed, the MP Services Protocol produces a collection of services
+/// that are needed for MP management.
+///
+/// Before the UEFI event EFI_EVENT_GROUP_READY_TO_BOOT is signaled, the module
+/// that produces this protocol is required to place all APs into an idle state
+/// whenever the APs are disabled or the APs are not executing code as requested
+/// through the StartupAllAPs() or StartupThisAP() services. The idle state of
+/// an AP before the UEFI event EFI_EVENT_GROUP_READY_TO_BOOT is signaled is
+/// implementation dependent.
+///
+/// After the UEFI event EFI_EVENT_GROUP_READY_TO_BOOT is signaled, all the APs
+/// must be placed in the OS compatible CPU state as defined by the UEFI
+/// Specification. Implementations of this protocol may use the UEFI event
+/// EFI_EVENT_GROUP_READY_TO_BOOT to force APs into the OS compatible state as
+/// defined by the UEFI Specification. Modules that use this protocol must
+/// guarantee that all non-blocking mode requests on all APs have been completed
+/// before the UEFI event EFI_EVENT_GROUP_READY_TO_BOOT is signaled. Since the
+/// order that event notification functions in the same event group are executed
+/// is not deterministic, an event of type EFI_EVENT_GROUP_READY_TO_BOOT cannot
+/// be used to guarantee that APs have completed their non-blocking mode requests.
+///
+/// When the UEFI event EFI_EVENT_GROUP_READY_TO_BOOT is signaled, the StartAllAPs()
+/// and StartupThisAp() services must no longer support non-blocking mode requests.
+/// The support for SwitchBSP() and EnableDisableAP() may no longer be supported
+/// after this event is signaled. Since UEFI Applications and UEFI OS Loaders
+/// execute after the UEFI event EFI_EVENT_GROUP_READY_TO_BOOT is signaled, these
+/// UEFI images must be aware that the functionality of this protocol may be reduced.
+///
+struct _EFI_PI_MP_SERVICES_PROTOCOL {
+ ///
+ /// This service retrieves the number of logical processor in the platform and the number of those logical
+ /// processors that are enabled on this boot. This service may only be called from the BSP.
+ ///
+ EFI_PI_MP_SERVICES_GET_NUMBER_OF_PROCESSORS GetNumberOfProcessors;
+ ///
+ /// This service retrieves detailed MP-related information about any processor on the platform.
+ ///
+ EFI_PI_MP_SERVICES_GET_PROCESSOR_INFO GetProcessorInfo;
+ ///
+ /// This service executes a caller provided function on all enabled APs.
+ ///
+ EFI_PI_MP_SERVICES_STARTUP_ALL_APS StartupAllAPs;
+ ///
+ /// This service lets the caller get one enabled AP to execute a caller-provided function.
+ ///
+ EFI_PI_MP_SERVICES_STARTUP_THIS_AP StartupThisAP;
+ ///
+ /// This service switches the requested AP to be the BSP from that point onward.
+ ///
+ EFI_PI_MP_SERVICES_SWITCH_BSP SwitchBSP;
+ ///
+ /// This service lets the caller enable or disable an AP from this point onward. This service may only be
+ /// called from the BSP.
+ ///
+ EFI_PI_MP_SERVICES_ENABLEDISABLEAP EnableDisableAP;
+ ///
+ /// This return the handle number for the calling processor. This service may be called from the BSP and APs.
+ ///
+ EFI_PI_MP_SERVICES_WHOAMI WhoAmI;
+};
+
+extern EFI_GUID gEfiPiMpServiceProtocolGuid;
+
+#endif
diff --git a/ReferenceCode/Haswell/Protocol/PowerMgmtInitDone/PowerMgmtInitDone.c b/ReferenceCode/Haswell/Protocol/PowerMgmtInitDone/PowerMgmtInitDone.c
new file mode 100644
index 0000000..6849c6e
--- /dev/null
+++ b/ReferenceCode/Haswell/Protocol/PowerMgmtInitDone/PowerMgmtInitDone.c
@@ -0,0 +1,42 @@
+/** @file
+ This file defines the Ppm Info Protocol.
+
+@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 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
+**/
+
+///
+/// Statements that include other files
+///
+///
+/// External include files do NOT need to be explicitly specified in real EDKII
+/// environment
+///
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#endif
+
+#include "PowerMgmtInitDone.h"
+
+///
+/// Protocol GUID definition
+///
+EFI_GUID gEfiPowerMgmtInitDoneProtocolGuid = EFI_POWER_MGMT_INIT_DONE_PROTOCOL_GUID;
+
+///
+/// Protocol description
+///
+EFI_GUID_STRING
+ (&gEfiPowerMgmtInitDoneProtocolGuid, "PowerMgmtInitDone Protocol", "Power Managment Initialization done Protocol");
diff --git a/ReferenceCode/Haswell/Protocol/PowerMgmtInitDone/PowerMgmtInitDone.h b/ReferenceCode/Haswell/Protocol/PowerMgmtInitDone/PowerMgmtInitDone.h
new file mode 100644
index 0000000..5de11d1
--- /dev/null
+++ b/ReferenceCode/Haswell/Protocol/PowerMgmtInitDone/PowerMgmtInitDone.h
@@ -0,0 +1,52 @@
+/** @file
+ This file defines the PowerMgmtInitDone Protocol.
+
+@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 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
+**/
+#ifndef _POWER_MGMT_INIT_DONE_H_
+#define _POWER_MGMT_INIT_DONE_H_
+
+///
+/// Define PPM INFO protocol GUID
+///
+/// EDK and EDKII have different GUID formats
+///
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#define EFI_POWER_MGMT_INIT_DONE_PROTOCOL_GUID \
+ { \
+ 0xd71db106, 0xe32d, 0x4225, 0xbf, 0xf4, 0xde, 0x6d, 0x77, 0x87, 0x17, 0x61 \
+ }
+
+#else
+#define EFI_POWER_MGMT_INIT_DONE_PROTOCOL_GUID \
+ { \
+ 0xd71db106, 0xe32d, 0x4225, \
+ { \
+ 0xbf, 0xf4, 0xde, 0x6d, 0x77, 0x87, 0x17, 0x61 \
+ } \
+ }
+#endif
+///
+/// Extern the GUID for protocol users.
+///
+extern EFI_GUID gEfiPowerMgmtInitDoneProtocolGuid;
+
+//
+// Forward reference for ANSI C compatibility
+//
+typedef struct _EFI_POWER_MGMT_INIT_DONE_PROTOCOL EFI_POWER_MGMT_INIT_DONE_PROTOCOL;
+
+#endif
diff --git a/ReferenceCode/Haswell/Protocol/PpmGlobalNvsArea/PpmGlobalNvsArea.c b/ReferenceCode/Haswell/Protocol/PpmGlobalNvsArea/PpmGlobalNvsArea.c
new file mode 100644
index 0000000..0c803c9
--- /dev/null
+++ b/ReferenceCode/Haswell/Protocol/PpmGlobalNvsArea/PpmGlobalNvsArea.c
@@ -0,0 +1,31 @@
+/** @file
+ Processor Power Management Global NVS Area description protocol implementation.
+
+@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 Mobile Silicon Support Module" and is
+ licensed for Intel Mobile 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
+**/
+#include "EdkIIGlueDxe.h"
+
+#include "PpmGlobalNvsArea.h"
+
+EFI_GUID gPpmGlobalNvsAreaProtocolGuid = EFI_PPM_GLOBAL_NVS_AREA_PROTOCOL_GUID;
+
+EFI_GUID_STRING
+(
+ &gPpmGlobalNvsAreaProtocolGuid, "PPM Global NVS Area Protocol",
+ "Protocol describing PPM ACPI NVS memory region used by ACPI subsystem."
+);
diff --git a/ReferenceCode/Haswell/Protocol/PpmGlobalNvsArea/PpmGlobalNvsArea.h b/ReferenceCode/Haswell/Protocol/PpmGlobalNvsArea/PpmGlobalNvsArea.h
new file mode 100644
index 0000000..ebae019
--- /dev/null
+++ b/ReferenceCode/Haswell/Protocol/PpmGlobalNvsArea/PpmGlobalNvsArea.h
@@ -0,0 +1,129 @@
+/** @file
+ Definition of the CPU PM global NVS area protocol. This protocol
+ publishes the address and format of a global ACPI NVS buffer used as a communications
+ buffer between SMM/DXE/PEI code and ASL code.
+ @todo The format is derived from the ACPI reference code, version 0.95.
+
+ Note: Data structures defined in this protocol are not naturally aligned.
+
+@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 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
+**/
+#ifndef _PPM_GLOBAL_NVS_AREA_H_
+#define _PPM_GLOBAL_NVS_AREA_H_
+
+///
+/// Forward reference for pure ANSI compatability
+///
+EFI_FORWARD_DECLARATION (PPM_GLOBAL_NVS_AREA_PROTOCOL);
+
+///
+/// Processor PM Global NVS Area Protocol GUID - {6C50CDCB-7F46-4dcc-8DDD-D9F0A3C61128}
+///
+#define EFI_PPM_GLOBAL_NVS_AREA_PROTOCOL_GUID \
+ { \
+ 0x6c50cdcb, 0x7f46, 0x4dcc, 0x8d, 0xdd, 0xd9, 0xf0, 0xa3, 0xc6, 0x11, 0x28 \
+ }
+
+///
+/// Extern the GUID for protocol users.
+///
+extern EFI_GUID gPpmGlobalNvsAreaProtocolGuid;
+
+//
+// Processor Power Management GlobalNvs Revisions
+//
+#define PPM_GLOBAL_NVS_AREA_REVISION_1 1 ///< Initial Version
+
+#pragma pack(1)
+
+typedef struct {
+ UINT16 CtdpPowerLimit1; ///< CTDP Power Limit1
+ UINT16 CtdpPowerLimit2; ///< CTDP Power Limit2
+ UINT8 CtdpPowerLimitWindow; ///< CTDP Power Limit Time Window
+ UINT8 CtdpCtc; ///< CTDP CTC
+ UINT8 CtdpTar; ///< CTDP TAR
+ UINT8 CtdpPpc; ///< CTDP PPC
+} PPM_CTDP_LEVEL_SETTINGS;
+
+///
+/// Global NVS Area definition
+///
+typedef struct {
+ UINT8 Revision; ///< (0) PPM GlobalNvs Revision
+ UINT32 PpmFlags; ///< (1-4) PPM Flags
+ UINT8 Reserved; ///< (5) Reserved
+ //
+ // Thermal Configuration Values
+ //
+ UINT8 AutoCriticalTripPoint; ///< (6) Auto Critical Trip Point
+ UINT8 AutoPassiveTripPoint; ///< (7) Auto Passive Trip Point
+ UINT8 AutoActiveTripPoint; ///< (8) Auto Active Trip Point
+ UINT32 Cpuid; ///< (9) CPUID
+ //
+ // ConfigTDP Values
+ //
+ UINT8 ConfigurablePpc; ///< (13) Boot Mode vlues for _PPC
+ //
+ // ConfigTDP Level settngs
+ //
+ UINT8 CustomConfigTdp; ///< (14) ConfigTdp Enabled/Disabled
+ UINT8 CtdpLevelsSupported; ///< (15) ConfigTdp Number Of Levels
+ UINT8 ConfigTdpBootModeIndex; ///< (16) CTDP Boot Mode Index
+ ///
+ /// (17) CTDP Level 0 Power Limit1
+ /// (19) CTDP Level 0 Power Limit2
+ /// (21) CTDP Level 0 Power Limit1 Time Window
+ /// (22) CTDP Level 0 CTC
+ /// (23) CTDP Level 0 TAR
+ /// (24) CTDP Level 0 PPC
+ /// (25) CTDP Level 1 Power Limit1
+ /// (27) CTDP Level 1 Power Limit2
+ /// (29) CTDP Level 1 Power Limit1 Time Window
+ /// (30) CTDP Level 1 CTC
+ /// (31) CTDP Level 1 TAR
+ /// (32) CTDP Level 1 PPC
+ /// (33) CTDP Level 2 Power Limit1
+ /// (35) CTDP Level 2 Power Limit2
+ /// (37) CTDP Level 2 Power Limit1 Time Window
+ /// (38) CTDP Level 2 CTC
+ /// (39) CTDP Level 2 TAR
+ /// (40) CTDP Level 2 PPC
+ ///
+ PPM_CTDP_LEVEL_SETTINGS CtdpLevelSettings[3];
+ //
+ // Mwait Hints and Latency values for C3/C6/C7/C7S
+ //
+ UINT8 C3MwaitValue; ///< (41) Mwait Hint value for C3
+ UINT8 C6MwaitValue; ///< (42) Mwait Hint value for C6
+ UINT8 C7MwaitValue; ///< (43) Mwait Hint value for C6
+ UINT8 CDMwaitValue; ///< (44) Mwait Hint value for C7/C8/C9/C10
+ UINT16 C3Latency; ///< (45-46) Latency value for C3
+ UINT16 C6Latency; ///< (47-48) Latency Value for C6
+ UINT16 C7Latency; ///< (49-50) Latency Value for C6
+ UINT16 CDLatency; ///< (51-52) Latency Value for C7/C8/C9/C10
+ UINT16 CDIOLevel; ///< (53-54) IO Level Value for C7/C8/C9/C10
+ UINT16 CDPowerValue; ///< (55-56) Power Value for C7/C8/C9/C10
+ UINT8 MiscPowerManagementFlags; ///< (57) MiscPowerManagementFlags
+} PPM_GLOBAL_NVS_AREA;
+#pragma pack()
+///
+/// PPM Global NVS Area Protocol
+///
+struct _PPM_GLOBAL_NVS_AREA_PROTOCOL {
+ PPM_GLOBAL_NVS_AREA *Area;
+};
+
+#endif
diff --git a/ReferenceCode/Haswell/Protocol/SmmThunk/SmmThunk.c b/ReferenceCode/Haswell/Protocol/SmmThunk/SmmThunk.c
new file mode 100644
index 0000000..fd03cf8
--- /dev/null
+++ b/ReferenceCode/Haswell/Protocol/SmmThunk/SmmThunk.c
@@ -0,0 +1,25 @@
+/** @file
+ This file defines SMM thunk abstraction protocol
+
+@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 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
+**/
+#include "Tiano.h"
+#include EFI_PROTOCOL_DEFINITION (SmmThunk)
+
+EFI_GUID gEfiSmmThunkProtocolGuid = EFI_SMM_THUNK_PROTOCOL_GUID;
+
+EFI_GUID_STRING(&gEfiSmmThunkProtocolGuid, "SMM Thunk Protocol", "SMM Thunk protocol");
diff --git a/ReferenceCode/Haswell/Protocol/SmmThunk/SmmThunk.h b/ReferenceCode/Haswell/Protocol/SmmThunk/SmmThunk.h
new file mode 100644
index 0000000..0c85718
--- /dev/null
+++ b/ReferenceCode/Haswell/Protocol/SmmThunk/SmmThunk.h
@@ -0,0 +1,64 @@
+/** @file
+ This file defines SMM Thunk abstraction protocol.
+
+@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 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
+**/
+#ifndef _SMM_THUNK_H_
+#define _SMM_THUNK_H_
+
+EFI_FORWARD_DECLARATION (EFI_SMM_THUNK_PROTOCOL);
+
+///
+/// include LegacyBios Protocol for IA32_REGISTER_SET
+///
+#include EFI_PROTOCOL_DEFINITION (LegacyBios)
+
+#define EFI_SMM_THUNK_PROTOCOL_GUID \
+ { \
+ 0x2a82fce6, 0x8bb6, 0x413e, 0xb9, 0xeb, 0x45, 0xdf, 0xc0, 0x52, 0x2d, 0xf3 \
+ }
+
+typedef
+BOOLEAN
+(EFIAPI *EFI_SMM_FARCALL86)(
+ IN EFI_SMM_THUNK_PROTOCOL *This,
+ IN UINT16 Segment,
+ IN UINT16 Offset,
+ IN OUT EFI_IA32_REGISTER_SET *Regs OPTIONAL,
+ IN VOID *Stack OPTIONAL,
+ IN UINTN StackSize
+ );
+
+typedef
+BOOLEAN
+(EFIAPI *EFI_SMM_INTCALL86)(
+ IN EFI_SMM_THUNK_PROTOCOL *This,
+ IN UINT16 Segment,
+ IN UINT16 Offset,
+ IN OUT EFI_IA32_REGISTER_SET *Regs OPTIONAL,
+ IN VOID *Stack OPTIONAL,
+ IN UINTN StackSize
+ );
+
+struct _EFI_SMM_THUNK_PROTOCOL {
+ EFI_SMM_FARCALL86 FarCall86;
+ EFI_SMM_INTCALL86 IntCall86;
+};
+
+extern EFI_GUID gEfiSmmThunkProtocolGuid;
+
+#endif
diff --git a/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Dxe/CpuPolicyDxe.cif b/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Dxe/CpuPolicyDxe.cif
new file mode 100644
index 0000000..123e37c
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Dxe/CpuPolicyDxe.cif
@@ -0,0 +1,13 @@
+<component>
+ name = "Cpu Policy DXE"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\SampleCode\CpuPolicyInit\Dxe"
+ RefName = "Cpu Policy Dxe"
+[files]
+"CpuPolicyDxe.mak"
+"CpuPolicyDxe.sdl"
+"CpuPolicyInitDxe.c"
+"CpuPolicyInitDxe.h"
+"CpuPolicyInitDxe.dxs"
+"CpuPolicyInitDxe.inf"
+<endComponent>
diff --git a/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Dxe/CpuPolicyDxe.mak b/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Dxe/CpuPolicyDxe.mak
new file mode 100644
index 0000000..da3c6dc
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Dxe/CpuPolicyDxe.mak
@@ -0,0 +1,92 @@
+# MAK file for the eModule:PowerManagement
+
+EDK : CpuPolicyInitDxe
+
+BUILD_CpuPolicyInitDxe_DIR = $(BUILD_DIR)\$(CpuPolicyInitDxe_DIR)
+
+$(BUILD_DIR)\CpuPolicyDxe.mak : $(CpuPolicyInitDxe_DIR)\CpuPolicyDxe.cif $(BUILD_RULES)
+ $(CIF2MAK) $(CpuPolicyInitDxe_DIR)\CpuPolicyDxe.cif $(CIF2MAK_DEFAULTS)
+
+CpuPolicyInitDxe : $(BUILD_DIR)\CpuPolicyDxe.MAK CpuPolicyInitDxeBin
+
+CpuInitDxe_OBJECTS = \
+ $(BUILD_CpuPolicyInitDxe_DIR)\CpuPolicyInitDxe.obj \
+
+CpuInitDxe_MY_INCLUDES= \
+ $(EDK_INCLUDES)\
+ $(PROJECT_CPU_INCLUDES)\
+ /I$(PROJECT_CPU_ROOT)\
+ /I$(UefiEfiIfrSupportLib_DIR)\
+ /I$(PROJECT_CPU_ROOT)\Include \
+
+CpuInitDxe_DEFINES = $(MY_DEFINES)\
+ /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=CpuPolicyInitDxeEntryPoint"\
+ /D TXT_SUPPORT_FLAG=1 \
+ /D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ /D __EDKII_GLUE_BASE_LIB__ \
+ /D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ /D __EDKII_GLUE_DXE_REPORT_STATUS_CODE_LIB__ \
+ /D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ /D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \
+ /D __EDKII_GLUE_UEFI_DEVICE_PATH_LIB__ \
+ /D FV_MICROCODE_BASE=$(FV_MICROCODE_BASE) \
+ /D __EDKII_GLUE_HII_LIB__ \
+ /D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ \
+!ifdef PACK_MICROCODE
+ /D PACK_MICROCODE=$(PACK_MICROCODE) \
+!else
+ /D PACK_MICROCODE=0 \
+!endif
+ /D SMM_FROM_SMBASE_DRIVER=$(SMM_FROM_SMBASE_DRIVER) \
+ /D MICROCODE_BLOCK_SIZE=$(MICROCODE_BLOCK_SIZE) \
+
+CpuInitDxe_LIBS =\
+ $(PchPlatformLib)\
+ $(EfiRuntimeLib_LIB)\
+ $(INTEL_PCH_PROTOCOL_LIB)\
+ $(EFIRUNTIMELIB)\
+ $(CPUIA32LIB)\
+ $(EFIPROTOCOLLIB)\
+ $(EdkIIGlueUefiLib_LIB)\
+ $(EdkIIGlueDxeReportStatusCodeLib_LIB)\
+ $(EdkIIGlueDxeHobLib_LIB)\
+ $(EdkIIGlueDxeDebugLibReportStatusCode_LIB)\
+ $(EdkIIGlueBaseLib_LIB)\
+ $(EdkIIGlueBasePciLibPciExpress_LIB)\
+ $(CpuGuidLib_LIB)\
+!IF $(EFI_SPECIFICATION_VERSION) >= 0x0002000A
+ $(UEFIEFIIFRSUPPORTLIB)\
+!ELSE
+ $(EFIIFRSUPPORTLIB) \
+!ENDIF
+!IF "$(x64_BUILD)"=="1"
+ $(EdkIIGlueBaseLibX64_LIB)\
+!ELSE
+ $(EdkIIGlueBaseLibIA32_LIB)\
+!ENDIF
+ $(EdkIIGlueDxeMemoryAllocationLib_LIB)\
+ $(EdkIIGlueBaseIoLibIntrinsic_LIB)\
+ $(EdkIIGlueUefiBootServicesTableLib_LIB)\
+ $(EdkIIGlueUefiDevicePathLib_LIB)\
+ $(CpuProtocolLib_LIB)\
+ $(EFIDRIVERLIB)\
+ $(CpuPlatformLib_LIB)\
+ $(PchPlatformDxeLib_LIB)\
+ $(EFISCRIPTLIB)
+
+CpuPolicyInitDxeBin : $(CpuInitDxe_LIBS)
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\CpuPolicyDxe.mak all\
+ NAME=CpuPolicyDxe\
+ MAKEFILE=$(BUILD_DIR)\CpuPolicyDxe.mak \
+ "MY_INCLUDES=$(CpuInitDxe_MY_INCLUDES)" \
+ "MY_DEFINES=$(CpuInitDxe_DEFINES)"\
+ OBJECTS="$(CpuInitDxe_OBJECTS)" \
+ GUID=15B9B6DA-00A9-4de7-B8E8-ED7AFB88F16E\
+ ENTRY_POINT=_ModuleEntryPoint \
+ TYPE=BS_DRIVER \
+ EDKIIModule=DXEDRIVER\
+ DEPEX1=$(CpuPolicyInitDxe_DIR)\CpuPolicyInitDxe.dxs \
+ DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX \
+ COMPRESS=1
+#-----------------------------------------------------------------------
diff --git a/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Dxe/CpuPolicyDxe.sdl b/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Dxe/CpuPolicyDxe.sdl
new file mode 100644
index 0000000..be33503
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Dxe/CpuPolicyDxe.sdl
@@ -0,0 +1,58 @@
+#****************************************************************************
+#****************************************************************************
+#** **
+#** (C)Copyright 1985-2011, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30071 **
+#** **
+#** Phone (770)-246-8600 **
+#** **
+#****************************************************************************
+#****************************************************************************
+#****************************************************************************
+# $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/Intel Haswell Cpu RC PKG/Cpu Policy DXE/CpuPolicyDxe.sdl 1 2/07/12 3:56a Davidhsieh $
+#
+# $Revision: 1 $
+#
+# $Date: 2/07/12 3:56a $
+#
+#****************************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/Intel Haswell Cpu RC PKG/Cpu Policy DXE/CpuPolicyDxe.sdl $
+#
+# 1 2/07/12 3:56a Davidhsieh
+#
+# 1 5/06/11 6:06a Davidhsieh
+# First release
+#
+#
+#****************************************************************************
+TOKEN
+ Name = "CpuDxePolicy_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable Cpu Pei init support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+End
+
+PATH
+ Name = "CpuPolicyInitDxe_DIR"
+End
+
+MODULE
+ Help = "Includes CpuPeiInit.mak to Project"
+ File = "CpuPolicyDxe.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\CpuPolicyDxe.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End
+
diff --git a/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Dxe/CpuPolicyInitDxe.c b/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Dxe/CpuPolicyInitDxe.c
new file mode 100644
index 0000000..f78b89e
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Dxe/CpuPolicyInitDxe.c
@@ -0,0 +1,461 @@
+/** @file
+ This file is SampleCode for Intel CPU DXE Platform Policy initialzation.
+
+@copyright
+ Copyright (c) 2009 - 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
+
+**/
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+
+#if (EFI_SPECIFICATION_VERSION >= 0x2000A)
+#include EFI_PROTOCOL_DEFINITION (HiiDatabase)
+#else
+#include EFI_PROTOCOL_DEFINITION (Hii)
+#endif
+#include EFI_PROTOCOL_DEFINITION (CpuInfo)
+#include "CpuPolicyInitDxe.h"
+#if (EFI_SPECIFICATION_VERSION >= 0x2000A)
+#include "UefiIfrLibrary.h"
+#endif
+
+//-#include "FlashMap.h"
+#include "CpuPlatformLib.h"
+
+#define SMM_FROM_SMBASE_DRIVER 0x55
+#define SW_SMI_FROM_SMMBASE SMM_FROM_SMBASE_DRIVER
+
+#define PLATFORM_CPU_MAX_FSB_FREQUENCY 1066
+#endif
+
+//(AMI_CHG+)>
+VOID CallDxeCpuPolicyInitList(
+ IN EFI_SYSTEM_TABLE *SystemTable,
+ IN OUT DXE_CPU_PLATFORM_POLICY_PROTOCOL *mCpuPolicyDataPtr);
+//<(AMI_CHG+)
+EFI_EXP_BASE10_DATA mCoreFrequencyList[] = {
+ { 0, 0}, ///< 0 Means "Auto", also, the first is the default.
+ {-1, 0} ///< End marker
+};
+
+EFI_EXP_BASE10_DATA mFsbFrequencyList[] = {
+ { 0, 0}, ///< 0 Means "Auto", also, the first is the default.
+ {-1, 0} ///< End marker
+};
+
+DXE_CPU_PLATFORM_POLICY_PROTOCOL mCpuPolicyData = { 0 };
+CPU_CONFIG mCpuConfig = { 0 };
+POWER_MGMT_CONFIG mCpuPmConfig = { 0 };
+SECURITY_CONFIG mSecurityConfig = { 0 };
+#if defined(TXT_SUPPORT_FLAG) && (TXT_SUPPORT_FLAG == 1)
+TXT_FUNCTION_CONFIG mTxtFunctionConfig = { 0 };
+#endif
+
+///
+/// Function implementations
+///
+/**
+ Platform function to get MAX CPU count
+
+ @param[in] This - platform policy protocol
+ @param[in] MaxThreadsPerCore - variable that will store MaxThreadsPerCore
+ @param[in] MaxCoresPerDie - variable that will store MaxCoresPerDie
+ @param[in] MaxDiesPerPackage - variable that will store MaxDiesPerPackage
+ @param[in] MaxPackages - variable that will store MaxPackages
+
+ @retval EFI_SUCCESS - Always return success
+**/
+EFI_STATUS
+EFIAPI
+PlatformCpuGetMaxCount (
+ IN DXE_CPU_PLATFORM_POLICY_PROTOCOL *This,
+ OUT UINT32 *MaxThreadsPerCore,
+ OUT UINT32 *MaxCoresPerDie,
+ OUT UINT32 *MaxDiesPerPackage,
+ OUT UINT32 *MaxPackages
+ )
+{
+ *MaxThreadsPerCore = 2;
+ *MaxCoresPerDie = 4;
+ *MaxDiesPerPackage = 1;
+ *MaxPackages = 1;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get CPU information
+
+ @param[in] This - platform policy protocol
+ @param[in] Location - structure that describe CPU location information
+ @param[in] PlatformCpuInfo - structure that will be updated for platform CPU information
+
+ @retval EFI_INVALID_PARAMETER - PlatformCpuInfo is NULL
+ @retval EFI_SUCCESS - platform CPU info structure has been updated
+**/
+EFI_STATUS
+EFIAPI
+PlatformCpuGetCpuInfo (
+ IN DXE_CPU_PLATFORM_POLICY_PROTOCOL *This,
+ IN CPU_PHYSICAL_LOCATION *Location,
+ IN OUT PLATFORM_CPU_INFORMATION *PlatformCpuInfo
+ )
+{
+#if (EFI_SPECIFICATION_VERSION < 0x2000A)
+ EFI_HII_PROTOCOL *Hii;
+#endif
+ STRING_REF SocketNameToken;
+ STRING_REF FillByOemToken;
+ EFI_STATUS Status;
+ UINT64 MsrValue;
+ UINT8 CpuSku;
+
+ SocketNameToken = 0;
+ FillByOemToken = 0;
+
+ ///
+ /// For Processor SocketName definition.
+ ///
+ if (PlatformCpuInfo == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+#if (EFI_SPECIFICATION_VERSION >= 0x2000A)
+ Status = IfrLibNewString (PlatformCpuInfo->StringHandle, &SocketNameToken, L"U3E1");
+ ASSERT_EFI_ERROR (Status);
+
+ Status = IfrLibNewString (PlatformCpuInfo->StringHandle, &FillByOemToken, L"To Be Filled By O.E.M.");
+ ASSERT_EFI_ERROR (Status);
+#else
+ Status = gBS->LocateProtocol (
+ &gEfiHiiProtocolGuid,
+ NULL,
+ (VOID **) &Hii
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Hii->NewString (
+ Hii,
+ NULL,
+ PlatformCpuInfo->StringHandle,
+ &SocketNameToken,
+ L"U3E1"
+ );
+
+ Hii->NewString (
+ Hii,
+ NULL,
+ PlatformCpuInfo->StringHandle,
+ &FillByOemToken,
+ L"To Be Filled By O.E.M."
+ );
+#endif
+
+ PlatformCpuInfo->ApicID = Location->Thread;
+ PlatformCpuInfo->ReferenceString = 0;
+ CpuSku = GetCpuSku ();
+ switch (CpuSku) {
+ case EnumCpuTrad:
+ PlatformCpuInfo->SocketType = 0x2d; // @todo EfiProcessorSocketLGA1150, pending updated SMBIOS spec release
+ break;
+
+ case EnumCpuUlt:
+ PlatformCpuInfo->SocketType = 0x2e; // @todo EfiProcessorSocketBGA1168, pending updated SMBIOS spec release
+ break;
+
+ default:
+ PlatformCpuInfo->SocketType = EfiProcessorSocketOther;
+ break;
+ }
+ PlatformCpuInfo->SocketName = SocketNameToken;
+
+ MsrValue = AsmReadMsr64 (MSR_PLATFORM_INFO);
+ PlatformCpuInfo->MaxCoreFrequency.Value = (100 * (((UINT32) MsrValue >> N_PLATFORM_INFO_MAX_RATIO) & B_PLATFORM_INFO_RATIO_MASK));
+ PlatformCpuInfo->MaxCoreFrequency.Exponent = 6;
+
+ PlatformCpuInfo->MaxFsbFrequency.Value = PLATFORM_CPU_MAX_FSB_FREQUENCY;
+ PlatformCpuInfo->MaxFsbFrequency.Exponent = 6;
+
+ PlatformCpuInfo->PlatformCoreFrequencyList = mCoreFrequencyList;
+ PlatformCpuInfo->PlatformFsbFrequencyList = mFsbFrequencyList;
+
+ PlatformCpuInfo->AssetTag = FillByOemToken;
+ PlatformCpuInfo->SerialNumber = FillByOemToken;
+ PlatformCpuInfo->PartNumber = FillByOemToken;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get the microcode patch.
+
+ @param[in] This - Driver context.
+ @param[in] MicrocodeData - Retrieved image of the microcode.
+
+ @retval EFI_SUCCESS - Image found.
+ @retval EFI_NOT_FOUND - image not found.
+**/
+EFI_STATUS
+PlatformCpuRetrieveMicrocode (
+ IN DXE_CPU_PLATFORM_POLICY_PROTOCOL *This,
+ OUT UINT8 **MicrocodeData
+ )
+{
+ /*EFI_CPU_MICROCODE_HEADER *Microcode;
+ UINTN MicrocodeStart;
+ UINTN MicrocodeEnd;
+ UINTN TotalSize;
+
+ ///
+ /// Microcode binary in SEC
+ ///
+ MicrocodeStart = FLASH_REGION_MICROCODE_BASE +
+ ((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) FLASH_REGION_MICROCODE_BASE)->HeaderLength +
+ sizeof (EFI_FFS_FILE_HEADER);
+
+ MicrocodeEnd = FLASH_REGION_MICROCODE_BASE + FLASH_REGION_MICROCODE_SIZE;
+
+ if (*MicrocodeData == NULL) {
+ *MicrocodeData = (UINT8 *) (UINTN) MicrocodeStart;
+ } else {
+ if (*MicrocodeData < (UINT8 *) (UINTN) MicrocodeStart) {
+ return EFI_NOT_FOUND;
+ }
+
+ TotalSize = (UINTN) (((EFI_CPU_MICROCODE_HEADER *) *MicrocodeData)->TotalSize);
+ if (TotalSize == 0) {
+ TotalSize = 2048;
+ }
+ //
+ // Add alignment check - begin
+ //
+ if ((TotalSize & 0x7FF) != 0) {
+ TotalSize = (TotalSize & 0xFFFFF800) + 0x800;
+ }
+ //
+ // Add alignment check - end
+ //
+
+ *MicrocodeData += TotalSize;
+
+ Microcode = (EFI_CPU_MICROCODE_HEADER *) *MicrocodeData;
+ if (*MicrocodeData >= (UINT8 *) (UINTN) (MicrocodeEnd) || Microcode->TotalSize == (UINT32) -1) {
+ return EFI_NOT_FOUND;
+ }
+
+ }
+
+
+ return EFI_SUCCESS;*/
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Initilize Intel Cpu DXE Platform Policy
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SystemTable Global system service table.
+
+ @retval EFI_SUCCESS Initialization complete.
+ @exception EFI_UNSUPPORTED The chipset is unsupported by this driver.
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver.
+ @retval EFI_DEVICE_ERROR Device error, driver exits abnormally.
+**/
+EFI_STATUS
+EFIAPI
+CpuPolicyInitDxeEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ CPU_FAMILY CpuFamilyId;
+
+ CpuFamilyId = GetCpuFamily();
+
+ mCpuPolicyData.Revision = DXE_PLATFORM_CPU_POLICY_PROTOCOL_REVISION_7;
+ mCpuPolicyData.CpuConfig = &mCpuConfig;
+ mCpuPolicyData.PowerMgmtConfig = &mCpuPmConfig;
+ mCpuPolicyData.SecurityConfig = &mSecurityConfig;
+
+ mCpuConfig.RetrieveMicrocode = PlatformCpuRetrieveMicrocode;
+ mCpuConfig.GetMaxCount = PlatformCpuGetMaxCount;
+ mCpuConfig.GetCpuInfo = PlatformCpuGetCpuInfo;
+ mSecurityConfig.TxtFunctionConfig = NULL;
+#ifdef TXT_SUPPORT_FLAG
+ mSecurityConfig.TxtFunctionConfig = &mTxtFunctionConfig;
+#endif // TXT_SUPPORT_FLAG
+ mCpuConfig.SmmbaseSwSmiNumber = SW_SMI_FROM_SMMBASE;
+
+ mCpuConfig.HtState = CPU_FEATURE_ENABLE;
+ mCpuConfig.LimitCpuidMaximumValue = CPU_FEATURE_DISABLE;
+ mCpuConfig.ExecuteDisableBit = CPU_FEATURE_ENABLE;
+ mCpuConfig.VmxEnable = CPU_FEATURE_ENABLE;
+ mCpuConfig.SmxEnable = CPU_FEATURE_ENABLE;
+ mCpuConfig.MachineCheckEnable = CPU_FEATURE_ENABLE;
+ mCpuConfig.MonitorMwaitEnable = CPU_FEATURE_ENABLE;
+ mCpuConfig.XapicEnable = CPU_FEATURE_DISABLE;
+ mCpuConfig.AesEnable = CPU_FEATURE_ENABLE;
+ mCpuConfig.DebugInterfaceEnable = CPU_FEATURE_DISABLE;
+ mCpuConfig.DebugInterfaceLockEnable = CPU_FEATURE_ENABLE;
+ mCpuConfig.MlcStreamerPrefetcher = CPU_FEATURE_ENABLE;
+ mCpuConfig.MlcSpatialPrefetcher = CPU_FEATURE_ENABLE;
+ mCpuConfig.EnableDts = CPU_FEATURE_DISABLE;
+ mCpuConfig.BspSelection = 0;
+ mCpuConfig.ApIdleManner = 1;
+ mCpuConfig.ApHandoffManner = 1;
+ ///
+ /// Virtual wire to A
+ ///
+ mCpuConfig.FviReport = 1;
+ ///
+ /// Default Enable FVI SMBIOS Report
+ ///
+ mCpuConfig.FviSmbiosType = 0xDD;
+ ///
+ /// Default SMBIOS Type 221
+ ///
+ /// Initialize Power Management Config
+ /// Allocate and set Power Management policy structure to recommended defaults
+ ///
+ mCpuPmConfig.pFunctionEnables = AllocateZeroPool (sizeof (PPM_FUNCTION_ENABLES));
+ mCpuPmConfig.pCustomRatioTable = AllocateZeroPool (sizeof (PPM_CUSTOM_RATIO_TABLE));
+ mCpuPmConfig.pTurboSettings = AllocateZeroPool (sizeof (PPM_TURBO_SETTINGS));
+ mCpuPmConfig.pRatioLimit = AllocateZeroPool ((sizeof (UINT8) * 4));
+ mCpuPmConfig.pPpmLockEnables = AllocateZeroPool (sizeof (PPM_LOCK_ENABLES));
+ mCpuPmConfig.pCustomCtdpSettings = AllocateZeroPool (sizeof (PPM_CUSTOM_CTDP));
+ mCpuPmConfig.ThermalFuncEnables = AllocateZeroPool (sizeof (THERM_FUNCTION_ENABLES));
+
+ if ((mCpuPmConfig.pFunctionEnables == NULL) ||
+ (mCpuPmConfig.pCustomRatioTable == NULL) ||
+ (mCpuPmConfig.pTurboSettings == NULL) ||
+ (mCpuPmConfig.pPpmLockEnables == NULL) ||
+ (mCpuPmConfig.pCustomCtdpSettings == NULL) ||
+ (mCpuPmConfig.ThermalFuncEnables == NULL)
+ ) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ mCpuPmConfig.pFunctionEnables->Eist = PPM_ENABLE;
+ mCpuPmConfig.pFunctionEnables->Cx = PPM_ENABLE;
+ mCpuPmConfig.pFunctionEnables->C1e = PPM_ENABLE;
+ mCpuPmConfig.pFunctionEnables->C3 = PPM_ENABLE;
+ mCpuPmConfig.pFunctionEnables->C6 = PPM_ENABLE;
+ if (CpuFamilyId == EnumCpuHswUlt) {
+ mCpuPmConfig.pFunctionEnables->C8 = PPM_ENABLE;
+ mCpuPmConfig.pFunctionEnables->C9 = PPM_ENABLE;
+ mCpuPmConfig.pFunctionEnables->C10 = PPM_ENABLE;
+ }
+ mCpuPmConfig.pFunctionEnables->DeepCState = DeepC7S;
+ mCpuPmConfig.pFunctionEnables->C1AutoDemotion = PPM_ENABLE;
+ mCpuPmConfig.pFunctionEnables->C3AutoDemotion = PPM_ENABLE;
+ mCpuPmConfig.pFunctionEnables->C1UnDemotion = PPM_ENABLE;
+ mCpuPmConfig.pFunctionEnables->C3UnDemotion = PPM_ENABLE;
+ mCpuPmConfig.pFunctionEnables->PkgCStateDemotion = PPM_DISABLE;
+ mCpuPmConfig.pFunctionEnables->PkgCStateUnDemotion = PPM_DISABLE;
+ mCpuPmConfig.ThermalFuncEnables->BiProcHot = PPM_ENABLE;
+ mCpuPmConfig.ThermalFuncEnables->DisableProcHotOut = PPM_DISABLE;
+ mCpuPmConfig.ThermalFuncEnables->DisableVRThermalAlert= PPM_DISABLE;
+ mCpuPmConfig.ThermalFuncEnables->ProcHotResponce = PPM_DISABLE;
+ mCpuPmConfig.ThermalFuncEnables->TStates = PPM_DISABLE;
+ mCpuPmConfig.pFunctionEnables->Xe = PPM_DISABLE;
+ mCpuPmConfig.pFunctionEnables->TurboMode = PPM_ENABLE;
+ mCpuPmConfig.pFunctionEnables->PowerLimit2 = PPM_ENABLE;
+ mCpuPmConfig.pFunctionEnables->EnergyEfficientPState = PPM_ENABLE;
+ mCpuPmConfig.pFunctionEnables->CStatePreWake = PPM_ENABLE;
+ mCpuPmConfig.ThermalFuncEnables->AutoThermalReporting = PPM_ENABLE;
+
+ mCpuPmConfig.pFunctionEnables->LongLatencyC6 = PPM_DISABLE;
+ mCpuPmConfig.pFunctionEnables->LongLatencyC7 = PPM_ENABLE;
+ mCpuPmConfig.ThermalFuncEnables->ThermalMonitor = PPM_ENABLE;
+ mCpuPmConfig.ThermalFuncEnables->Pl1ThermalControl = 2; ///< AUTO
+ mCpuPmConfig.ThermalFuncEnables->Pl1ThermalControlFloor.FloorIA = Percent100;
+ mCpuPmConfig.ThermalFuncEnables->Pl1ThermalControlFloor.FloorGT = Percent100;
+ mCpuPmConfig.ThermalFuncEnables->Pl1ThermalControlFloor.FloorPCH = Percent100;
+ mCpuPmConfig.pFunctionEnables->LakeTiny = PPM_DISABLE;
+ mCpuPmConfig.pFunctionEnables->TimedMwait = PPM_DISABLE;
+
+ mCpuPmConfig.CustomPowerUnit = PowerUnit125MilliWatts;
+ mCpuPmConfig.pTurboSettings->PowerLimit1 = AUTO;
+ mCpuPmConfig.pTurboSettings->PowerLimit2 = AUTO;
+ mCpuPmConfig.pTurboSettings->PowerLimit1Time = AUTO;
+ mCpuPmConfig.pTurboSettings->PowerLimit3 = AUTO;
+ mCpuPmConfig.pTurboSettings->PowerLimit3Time = AUTO;
+ mCpuPmConfig.pTurboSettings->PowerLimit3DutyCycle = AUTO;
+ mCpuPmConfig.pTurboSettings->PowerLimit3Lock = PPM_ENABLE;
+ mCpuPmConfig.pTurboSettings->ConfigTdpLevel = 0;
+ mCpuPmConfig.pTurboSettings->ConfigTdpLock = PPM_DISABLE;
+ mCpuPmConfig.pCustomCtdpSettings->ConfigTdpCustom = PPM_DISABLE;
+
+ mCpuPmConfig.pTurboSettings->TurboPowerLimitLock = PPM_DISABLE;
+ mCpuPmConfig.pTurboSettings->EnergyPolicy = 0;
+
+ mCpuPmConfig.pPpmLockEnables->PmgCstCfgCtrlLock = PPM_ENABLE;
+ mCpuPmConfig.pPpmLockEnables->OverclockingLock = PPM_DISABLE;
+ mCpuPmConfig.pPpmLockEnables->ProcHotLock = PPM_DISABLE;
+ mCpuPmConfig.S3RestoreMsrSwSmiNumber = SW_SMI_S3_RESTORE_MSR;
+ mCpuPmConfig.PkgCStateLimit = PkgAuto;
+
+ mCpuPmConfig.CstateLatencyControl0TimeUnit = TimeUnit1024ns;
+ mCpuPmConfig.CstateLatencyControl1TimeUnit = TimeUnit1024ns;
+ mCpuPmConfig.CstateLatencyControl2TimeUnit = TimeUnit1024ns;
+ mCpuPmConfig.CstateLatencyControl0Irtl = C3_LATENCY;
+ mCpuPmConfig.CstateLatencyControl1Irtl = C6_C7_SHORT_LATENCY;
+ mCpuPmConfig.CstateLatencyControl2Irtl = C6_C7_LONG_LATENCY;
+ if (CpuFamilyId == EnumCpuHswUlt) {
+ mCpuPmConfig.CstateLatencyControl3TimeUnit = TimeUnit1024ns;
+ mCpuPmConfig.CstateLatencyControl4TimeUnit = TimeUnit1024ns;
+ mCpuPmConfig.CstateLatencyControl5TimeUnit = TimeUnit1024ns;
+ mCpuPmConfig.CstateLatencyControl3Irtl = C8_LATENCY;
+ mCpuPmConfig.CstateLatencyControl4Irtl = C9_LATENCY;
+ //
+ // If PS4 is disabled, program 2750us to MSR_C_STATE_LATENCY_CONTROL_5
+ //
+ mCpuPmConfig.CstateLatencyControl5Irtl = C10_LATENCY;
+ }
+ mCpuPmConfig.RfiFreqTunningOffsetIsNegative = 0;
+ mCpuPmConfig.RfiFreqTunningOffset = 0;
+
+ if (CpuFamilyId == EnumCpuHswUlt) {
+ //
+ // Calibrate 24MHz BCLK support; 0: NO_CALIBRATE, 1: PCODE_CALIBRATE, 2: BIOS_CALIBRATE (Default :1)
+ //
+ mCpuPmConfig.PcodeCalibration = 1;
+ mCpuPmConfig.EnableRerunPcodeCalibration = PPM_DISABLE;
+ }
+ ///
+ /// TxT platform config initiate
+ ///
+#if defined(TXT_SUPPORT_FLAG) && (TXT_SUPPORT_FLAG == 1)
+ mTxtFunctionConfig.ResetAux = 0;
+#endif
+
+ //AMI_REMOVE_TEMP_FOR_COMPILE
+ //UpdateDxeCpuPlatformPolicy (&mCpuPolicyData); //(AMI_CHG)
+ CallDxeCpuPolicyInitList(SystemTable, &mCpuPolicyData); // (AMI_CHG+)
+ ///
+ /// Install the DXE_CPU_PLATFORM_POLICY_PROTOCOL interface
+ ///
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gDxeCpuPlatformPolicyProtocolGuid,
+ &mCpuPolicyData,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
diff --git a/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Dxe/CpuPolicyInitDxe.dxs b/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Dxe/CpuPolicyInitDxe.dxs
new file mode 100644
index 0000000..7ff094a
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Dxe/CpuPolicyInitDxe.dxs
@@ -0,0 +1,42 @@
+/** @file
+ Dependency expression source file.
+
+@copyright
+ Copyright (c) 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
+
+**/
+
+
+//
+// Common for R8 and R9 codebase
+//
+#include "AutoGen.h"
+#include "PeimDepex.h"
+
+//
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are both "defined" in R8 codebase;
+// BUILD_WITH_EDKII_GLUE_LIB is defined in Edk-Dev-Snapshot-20070228 and later version
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are "not defined" in R9 codebase.
+//
+#if defined (BUILD_WITH_GLUELIB) || defined (BUILD_WITH_EDKII_GLUE_LIB)
+#include "EfiDepex.h"
+#endif
+
+#include EFI_ARCH_PROTOCOL_DEFINITION (Variable)
+
+
+DEPENDENCY_START
+ EFI_VARIABLE_ARCH_PROTOCOL_GUID
+DEPENDENCY_END \ No newline at end of file
diff --git a/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Dxe/CpuPolicyInitDxe.h b/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Dxe/CpuPolicyInitDxe.h
new file mode 100644
index 0000000..8524faf
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Dxe/CpuPolicyInitDxe.h
@@ -0,0 +1,50 @@
+/** @file
+ Header file for the CpuPolicyInitDxe Driver.
+
+@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 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
+**/
+#ifndef _CPU_PLATFORM_POLICY_DXE_H_
+#define _CPU_PLATFORM_POLICY_DXE_H_
+
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "CpuAccess.h"
+#endif
+
+#include "UefiIfrLibrary.h"
+#include "PowermgmtDefinitions.h"
+#include EFI_PROTOCOL_PRODUCER (CpuPlatformPolicy)
+//AMI_REMOVE_FOR_COMPILE
+//#include "CpuPlatformPolicyUpdateDxeLib.h"
+
+/**
+ Initilize Intel CPU DXE Policy
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SystemTable Global system service table.
+
+ @retval EFI_SUCCESS Initialization complete.
+ @exception EFI_UNSUPPORTED The chipset is unsupported by this driver.
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver.
+ @retval EFI_DEVICE_ERROR Device error, driver exits abnormally.
+**/
+EFI_STATUS
+CpuPolicyInitDxeEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN OUT EFI_SYSTEM_TABLE *SystemTable
+ );
+
+#endif
diff --git a/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Dxe/CpuPolicyInitDxe.inf b/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Dxe/CpuPolicyInitDxe.inf
new file mode 100644
index 0000000..b331411
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Dxe/CpuPolicyInitDxe.inf
@@ -0,0 +1,93 @@
+## @file
+# Component description file for the CpuPolicyInitDxe DXE driver.
+#
+#@copyright
+# Copyright (c) 2010 - 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
+#
+
+[defines]
+BASE_NAME = CpuPolicyInitDxe
+FILE_GUID = 15B9B6DA-00A9-4de7-B8E8-ED7AFB88F16E
+COMPONENT_TYPE = BS_DRIVER
+
+[sources.common]
+ CpuPolicyInitDxe.h
+ CpuPolicyInitDxe.c
+#
+# Edk II Glue Driver Entry Point
+#
+ EdkIIGlueDxeDriverEntryPoint.c
+
+[includes.common]
+ $(DEST_DIR)
+ $(BUILD_DIR)/$(PROCESSOR)
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include/Pcd
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Cpu/Pentium/Include
+#
+# if (EFI_SPECIFICATION_VERSION < 0x0002000A), use EfiIfrSupportLib
+# if (EFI_SPECIFICATION_VERSION >= 0x0002000A), use UefiEfiIfrSupportLib
+#
+# $(EDK_SOURCE)/Foundation/Library/Dxe/EfiIfrSupportLib
+ $(EDK_SOURCE)/Foundation/Library/Dxe/UefiEfiIfrSupportLib
+ $(EFI_SOURCE)
+ $(EFI_SOURCE)/Include
+ $(EFI_SOURCE)/Library/CpuPolicyInitLib/Dxe
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include/Library
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Samplecode/Include
+ $(EFI_SOURCE)/$(PROJECT_SA_ROOT)/Include
+
+[libraries.common]
+ EdkIIGlueDxeReportStatusCodeLib
+ EdkIIGlueDxeDebugLibReportStatusCode
+ EdkIIGlueDxeMemoryAllocationLib
+ EdkIIGlueUefiBootServicesTableLib
+ EdkIIGlueUefiRuntimeServicesTableLib
+ EdkFrameworkProtocolLib
+ EdkProtocolLib
+#
+# if (EFI_SPECIFICATION_VERSION < 0x0002000A), use EfiIfrSupportLib
+# if (EFI_SPECIFICATION_VERSION >= 0x0002000A), use UefiEfiIfrSupportLib, EfiDriverLib
+#
+# EfiIfrSupportLib
+ EfiDriverLib
+ UefiEfiIfrSupportLib
+ CpuProtocolLib
+ CpuIA32Lib
+ PlatformPolicyUpdateDxeLib
+ CpuPlatformLib
+
+[nmake.common]
+ IMAGE_ENTRY_POINT = _ModuleEntryPoint
+ DPX_SOURCE = CpuPolicyInitDxe.dxs
+#
+# Module Entry Point
+#
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=CpuPolicyInitDxeEntryPoint
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_DXE_REPORT_STATUS_CODE_LIB__ \
+ -D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ -D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__
diff --git a/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Pei/CpuPolicyInitPei.c b/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Pei/CpuPolicyInitPei.c
new file mode 100644
index 0000000..c0badcf
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Pei/CpuPolicyInitPei.c
@@ -0,0 +1,268 @@
+/** @file
+ This file is SampleCode for Intel CPU PEI Platform Policy initialization.
+
+@copyright
+ Copyright (c) 2010 - 2014 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 "CpuPolicyInitPei.h"
+
+//(AMI_CHG+)>
+VOID CallPeiCpuPolicyInitList(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT PEI_CPU_PLATFORM_POLICY_PPI *PeiCpuPolicyPpi);
+//<(AMI_CHG+)
+/**
+ This PEIM performs CPU PEI Platform Policy initialization.
+
+ @param[in] FfsHeader Pointer to Firmware File System file header.
+ @param[in] PeiServices General purpose services available to every PEIM.
+
+ @retval EFI_SUCCESS The PPI is installed and initialized.
+ @retval EFI ERRORS The PPI is not successfully installed.
+**/
+EFI_STATUS
+EFIAPI
+CpuPolicyInitPeiEntryPoint (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_PPI_DESCRIPTOR *CpuPlatformPolicyPpiDesc;
+ PEI_CPU_PLATFORM_POLICY_PPI *CpuPlatformPolicyPpi;
+ CPU_CONFIG_PPI *CpuConfig;
+ SECURITY_CONFIG_PPI *SecurityConfig;
+ PFAT_CONFIG *PfatConfig;
+ POWER_MGMT_CONFIG_PPI *PowerMgmtConfig;
+ OVERCLOCKING_CONFIG_PPI *OcConfig;
+ BOOT_GUARD_CONFIG *BootGuardConfig;
+#if defined(TXT_SUPPORT_FLAG) && (TXT_SUPPORT_FLAG == 1)
+ TXT_CONFIG *TxtConfig;
+#endif
+ UINT8 PlatIdStr[] = "SHARK BAY";
+
+ ///
+ /// Allocate memory for the CPU Policy Ppi and Descriptor
+ ///
+ Status = ((*PeiServices)->AllocatePool)(PeiServices, sizeof (EFI_PEI_PPI_DESCRIPTOR), &CpuPlatformPolicyPpiDesc);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = ((*PeiServices)->AllocatePool)(PeiServices, sizeof (PEI_CPU_PLATFORM_POLICY_PPI), &CpuPlatformPolicyPpi);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = ((*PeiServices)->AllocatePool)(PeiServices, sizeof (CPU_CONFIG_PPI), &CpuConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = ((*PeiServices)->AllocatePool)(PeiServices, sizeof (SECURITY_CONFIG_PPI), &SecurityConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = ((*PeiServices)->AllocatePool)(PeiServices, sizeof (PFAT_CONFIG), &PfatConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = ((*PeiServices)->AllocatePool)(PeiServices, sizeof (POWER_MGMT_CONFIG_PPI), &PowerMgmtConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = ((*PeiServices)->AllocatePool)(PeiServices, sizeof (OVERCLOCKING_CONFIG_PPI), &OcConfig);
+ ASSERT_EFI_ERROR (Status);
+
+#if defined(TXT_SUPPORT_FLAG) && (TXT_SUPPORT_FLAG == 1)
+ Status = ((*PeiServices)->AllocatePool)(PeiServices, sizeof (TXT_CONFIG), &TxtConfig);
+ ASSERT_EFI_ERROR (Status);
+#endif
+
+ Status = ((*PeiServices)->AllocatePool) (PeiServices, sizeof (BOOT_GUARD_CONFIG), &BootGuardConfig);
+ ASSERT_EFI_ERROR (Status);
+
+ CpuPlatformPolicyPpi->Revision = PEI_CPU_PLATFORM_POLICY_PPI_REVISION_8;
+ CpuPlatformPolicyPpi->CpuConfig = CpuConfig;
+ CpuPlatformPolicyPpi->SecurityConfig = SecurityConfig;
+ CpuPlatformPolicyPpi->SecurityConfig->PfatConfig = PfatConfig;
+ CpuPlatformPolicyPpi->PowerMgmtConfig = PowerMgmtConfig;
+ CpuPlatformPolicyPpi->OverclockingConfig = OcConfig;
+ CpuPlatformPolicyPpi->CpuPlatformPpiPtr = (UINTN) CpuPlatformPolicyPpi;
+
+#if defined(TXT_SUPPORT_FLAG) && (TXT_SUPPORT_FLAG == 1)
+ CpuPlatformPolicyPpi->SecurityConfig->TxtConfig = TxtConfig;
+#else
+ CpuPlatformPolicyPpi->SecurityConfig->TxtConfig = NULL;
+#endif
+
+ CpuPlatformPolicyPpi->SecurityConfig->BootGuardConfig = BootGuardConfig;
+
+ CpuConfig->CpuRatioOverride = CPU_FEATURE_DISABLE;
+ CpuConfig->CpuRatio = 63;
+ CpuConfig->CpuMaxNonTurboRatio = 63;
+ CpuConfig->BistOnReset = CPU_FEATURE_DISABLE;
+ CpuConfig->HyperThreading = CPU_FEATURE_ENABLE;
+ CpuConfig->VmxEnable = CPU_FEATURE_ENABLE;
+ CpuConfig->ActiveCoreCount = 0;
+
+ ///
+ /// If CpuConfig->Pfat is set to ENABLE '1' then
+ /// PlatformData->SmmBwp (found in PchPolicyInitPei.c file) has to be set to ENABLE '1'
+ /// This is a PFAT Security requirement that needs to be addressed
+ /// If CpuConfig->Pfat is set to DISABLE '0' then
+ /// PlatformData->SmmBwp (found in PchPolicyInitPei.c file) value don't care, it can be
+ /// set to either ENABLE '1' or DISABLE '0' based on customer implementation
+ ///
+ CpuConfig->Pfat = CPU_FEATURE_DISABLE;
+ ZeroMem (&PfatConfig->Ppdt, sizeof (PPDT));
+ PfatConfig->Ppdt.PpdtMajVer = PPDT_MAJOR_VERSION;
+ PfatConfig->Ppdt.PpdtMinVer = PPDT_MINOR_VERSION;
+ CopyMem (&PfatConfig->Ppdt.PlatId[0], &PlatIdStr[0], sizeof (PlatIdStr));
+ PfatConfig->Ppdt.PfatModSvn = PFAT_SVN;
+ PfatConfig->Ppdt.BiosSvn = 0x01380000;
+ PfatConfig->Ppdt.ExecLim = 0;
+ PfatConfig->Ppdt.PlatAttr = 0;
+ PfatConfig->Ppdt.LastSfam = MIN_SFAM_COUNT - 1;
+ if (PfatConfig->Ppdt.LastSfam > (MAX_SFAM_COUNT - 1)) {
+ PfatConfig->Ppdt.LastSfam = MAX_SFAM_COUNT - 1;
+ }
+ ///
+ /// SfamData [LastSfam + 1]
+ ///
+ PfatConfig->Ppdt.SfamData[0].FirstByte = 0x00580000;
+ PfatConfig->Ppdt.SfamData[0].LastByte = 0x0058FFFF;
+ PfatConfig->Ppdt.PpdtSize = (sizeof (PPDT) - sizeof (PfatConfig->Ppdt.SfamData) + ((PfatConfig->Ppdt.LastSfam + 1) * sizeof (SFAM_DATA)));
+ PfatConfig->PpdtHash[0] = 0xae7295370672663c;
+ PfatConfig->PpdtHash[1] = 0x220375c996d23a36;
+ PfatConfig->PpdtHash[2] = 0x73aaea0f2afded9d;
+ PfatConfig->PpdtHash[3] = 0x707193b768a0829e;
+ ZeroMem (&PfatConfig->PupHeader, sizeof (PUP_HEADER));
+ PfatConfig->PupHeader.Version = PUP_HDR_VERSION;
+ CopyMem (&PfatConfig->PupHeader.PlatId[0], &PlatIdStr[0], sizeof (PlatIdStr));
+ PfatConfig->PupHeader.PkgAttributes = 0;
+ PfatConfig->PupHeader.PslMajorVer = PSL_MAJOR_VERSION;
+ PfatConfig->PupHeader.PslMinorVer = PSL_MINOR_VERSION;
+ PfatConfig->PupHeader.BiosSvn = PfatConfig->Ppdt.BiosSvn;
+ PfatConfig->PupHeader.EcSvn = 0;
+ PfatConfig->PupHeader.VendorSpecific = 0x808655AA;
+ ZeroMem (&PfatConfig->PfatLog, sizeof (PFAT_LOG));
+ PfatConfig->PfatLog.Version = PFAT_LOG_VERSION;
+ PfatConfig->PfatLog.LastPage = 0;
+ if (PfatConfig->PfatLog.LastPage > (MAX_PFAT_LOG_PAGE - 1)) {
+ PfatConfig->PfatLog.LastPage = MAX_PFAT_LOG_PAGE - 1;
+ }
+ PfatConfig->PfatLog.LoggingOptions = 0;
+ PfatConfig->NumSpiComponents = 2;
+ PfatConfig->ComponentSize[0] = EnumSpiCompSize8MB;
+ PfatConfig->ComponentSize[1] = EnumSpiCompSize8MB;
+ PfatConfig->PfatMemSize = 0x05;
+
+ CpuConfig->MlcStreamerPrefetcher = CPU_FEATURE_ENABLE;
+ CpuConfig->MlcSpatialPrefetcher = CPU_FEATURE_ENABLE;
+
+ PowerMgmtConfig->RatioLimit[0] = 0;
+ PowerMgmtConfig->RatioLimit[1] = 0;
+ PowerMgmtConfig->RatioLimit[2] = 0;
+ PowerMgmtConfig->RatioLimit[3] = 0;
+ PowerMgmtConfig->TccActivationOffset = 0;
+ PowerMgmtConfig->VrCurrentLimit = VR_CURRENT_DEFAULT;
+ PowerMgmtConfig->VrCurrentLimitLock = CPU_FEATURE_DISABLE;
+ PowerMgmtConfig->Xe = CPU_FEATURE_DISABLE;
+ PowerMgmtConfig->BootInLfm = CPU_FEATURE_DISABLE;
+ ///
+ /// VrMiscIoutSlope = 0x200 default
+ /// VrMiscIoutOffsetSign = 0 means it's positive offset. 1= negative offset
+ /// VrMiscIoutOffset = 0 means it's 0%, 625 means 6.25% (range is +6.25% ~ -6.25%)
+ ///
+ PowerMgmtConfig->VrMiscIoutSlope = 0x200;
+ PowerMgmtConfig->VrMiscIoutOffsetSign = 0;
+ PowerMgmtConfig->VrMiscIoutOffset = 0;
+
+ PowerMgmtConfig->VrMiscMinVid = V_MSR_VR_MISC_CONFIG_MIN_VID_DEFAULT;
+ PowerMgmtConfig->VrMiscIdleExitRampRate = CPU_FEATURE_ENABLE;
+ PowerMgmtConfig->VrMiscIdleEntryRampRate = CPU_FEATURE_DISABLE;
+ PowerMgmtConfig->VrMiscIdleEntryDecayEnable = CPU_FEATURE_ENABLE;
+ if (GetCpuFamily() == EnumCpuHswUlt) {
+ PowerMgmtConfig->VrMiscSlowSlewRateConfig = V_MSR_VR_MISC_CONFIG_SLOW_SLEW_RATE_CONFIG_DEFAULT;
+ PowerMgmtConfig->VrMisc2FastRampVoltage = V_MSR_VR_MISC_CONFIG2_FAST_RAMP_VOLTAGE_DEFAULT;
+ PowerMgmtConfig->VrMisc2MinC8Voltage = V_MSR_VR_MISC_CONFIG2_MIN_C8_VOLTAGE_DEFAULT;
+ PowerMgmtConfig->VrPSI4enable = CPU_FEATURE_ENABLE;
+ }
+ PowerMgmtConfig->Psi1Threshold = PSI1_THRESHOLD_DEFAULT;
+ PowerMgmtConfig->Psi2Threshold = PSI2_THRESHOLD_DEFAULT;
+ PowerMgmtConfig->Psi3Threshold = PSI3_THRESHOLD_DEFAULT;
+
+ PowerMgmtConfig->FivrSscEnable = 1;
+ PowerMgmtConfig->FivrSscPercent = 62;
+
+ ///
+ /// Initiate TxT policy
+ ///
+#if defined(TXT_SUPPORT_FLAG) && (TXT_SUPPORT_FLAG == 1)
+ ZeroMem (TxtConfig, sizeof (TXT_CONFIG));
+ CpuConfig->Txt = 0;
+ TxtConfig->SinitMemorySize = TXT_SINIT_MEMORY_SIZE;
+ TxtConfig->TxtHeapMemorySize = TXT_HEAP_MEMORY_SIZE;
+ TxtConfig->TxtDprMemoryBase = 0;
+ TxtConfig->TxtDprMemorySize = 0;
+ TxtConfig->BiosAcmBase = 0;
+ TxtConfig->BiosAcmSize = 0;
+ TxtConfig->McuUpdateDataAddr = 0;
+ TxtConfig->TgaSize = TXT_TGA_MEMORY_SIZE;
+ TxtConfig->TxtLcpPdBase = TXT_LCP_PD_BASE;
+ TxtConfig->TxtLcpPdSize = TXT_LCP_PD_SIZE;
+#endif
+ ///
+ /// Initialize Overclocking Data
+ ///
+ OcConfig->CoreVoltageOffset = 0;
+ OcConfig->CoreVoltageOverride = 0;
+ OcConfig->CoreExtraTurboVoltage = 0;
+ OcConfig->CoreMaxOcTurboRatio = 0;
+ OcConfig->ClrVoltageOffset = 0;
+ OcConfig->ClrVoltageOverride = 0;
+ OcConfig->ClrExtraTurboVoltage = 0;
+ OcConfig->ClrMaxOcTurboRatio = 0;
+ OcConfig->SvidVoltageOverride = 0;
+ OcConfig->SvidEnable = 0;
+ OcConfig->FivrFaultsEnable = 0;
+ OcConfig->FivrEfficiencyEnable = 0;
+ OcConfig->CoreVoltageMode = 0;
+ OcConfig->ClrVoltageMode = 0;
+ OcConfig->OcSupport = 0;
+ OcConfig->BitReserved = 0;
+
+ //
+ // Initialize Boot Guard data
+ //
+ BootGuardConfig->TpmType = TpmTypeMax;
+ BootGuardConfig->BypassTpmInit = FALSE;
+ BootGuardConfig->MeasuredBoot = FALSE;
+ BootGuardConfig->BootGuardSupport = FALSE;
+ BootGuardConfig->DisconnectAllTpms = FALSE;
+ BootGuardConfig->ByPassTpmEventLog = FALSE;
+
+ //AMI_CHG
+ //UpdatePeiCpuPlatformPolicy (PeiServices, CpuPlatformPolicyPpi); //(AMI_CHG)
+ CallPeiCpuPolicyInitList(PeiServices, CpuPlatformPolicyPpi); // (AMI_CHG+)
+
+ ///
+ /// Update the CPU Policy Ppi Descriptor
+ ///
+ CpuPlatformPolicyPpiDesc->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
+ CpuPlatformPolicyPpiDesc->Guid = &gPeiCpuPlatformPolicyPpiGuid;
+ CpuPlatformPolicyPpiDesc->Ppi = CpuPlatformPolicyPpi;
+
+ ///
+ /// Install the CPU PEI Platform Policy PPI
+ ///
+ Status = (**PeiServices).InstallPpi (PeiServices, CpuPlatformPolicyPpiDesc);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Pei/CpuPolicyInitPei.dxs b/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Pei/CpuPolicyInitPei.dxs
new file mode 100644
index 0000000..1e93c04
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Pei/CpuPolicyInitPei.dxs
@@ -0,0 +1,41 @@
+/** @file
+ Dependency expression source file.
+
+@copyright
+ Copyright (c) 2010 - 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
+
+**/
+
+
+//
+// Common for R8 and R9 codebase
+//
+#include "AutoGen.h"
+#include "PeimDepex.h"
+
+//
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are both "defined" in R8 codebase;
+// BUILD_WITH_EDKII_GLUE_LIB is defined in Edk-Dev-Snapshot-20070228 and later version
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are "not defined" in R9 codebase.
+//
+#if defined (BUILD_WITH_GLUELIB) || defined (BUILD_WITH_EDKII_GLUE_LIB)
+#include "EfiDepex.h"
+#endif
+
+#include EFI_PPI_DEPENDENCY (Variable)
+
+DEPENDENCY_START
+ PEI_READ_ONLY_VARIABLE_ACCESS_PPI_GUID
+DEPENDENCY_END
diff --git a/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Pei/CpuPolicyInitPei.h b/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Pei/CpuPolicyInitPei.h
new file mode 100644
index 0000000..47a9f2b
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Pei/CpuPolicyInitPei.h
@@ -0,0 +1,55 @@
+/** @file
+ Header file for the CpuPeiPolicy PEIM.
+
+@copyright
+ Copyright (c) 2009 - 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
+**/
+#ifndef _CPU_POLICY_INIT_PEI_H_
+#define _CPU_POLICY_INIT_PEI_H_
+
+///
+/// External include files do NOT need to be explicitly specified in real EDKII
+/// environment
+///
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGluePeim.h"
+#include "PfatDefinitions.h"
+#include EFI_PPI_PRODUCER (CpuPlatformPolicy)
+#include "CpuInitPeim.h"
+#include "CpuRegs.h"
+#include "CpuPlatformLib.h"
+#include "PowerMgmtDefinitions.h"
+#endif
+//#include "CpuPlatformPolicyUpdatePeiLib.h" //(AMI_CHG)
+
+///
+/// Functions
+///
+/**
+ This PEIM performs CPU PEI Platform Policy initialzation.
+
+ @param[in] FfsHeader Pointer to Firmware File System file header.
+ @param[in] PeiServices General purpose services available to every PEIM.
+
+ @retval EFI_SUCCESS The PPI is installed and initialized.
+ @retval EFI ERRORS The PPI is not successfully installed.
+**/
+EFI_STATUS
+EFIAPI
+CpuPolicyInitPeiEntryPoint (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices
+ );
+#endif
diff --git a/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Pei/CpuPolicyInitPei.inf b/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Pei/CpuPolicyInitPei.inf
new file mode 100644
index 0000000..1a07029
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Pei/CpuPolicyInitPei.inf
@@ -0,0 +1,87 @@
+## @file
+# Component description file for the CpuPolicyInitPei PEIM.
+#
+#@copyright
+# Copyright (c) 2010 - 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
+#
+
+[defines]
+BASE_NAME = CpuPolicyInitPei
+FILE_GUID = 567F05DE-D174-48e4-A7C0-C19868A11F9B
+COMPONENT_TYPE = PE32_PEIM
+
+[sources.common]
+ CpuPolicyInitPei.h
+ CpuPolicyInitPei.c
+#
+# Edk II Glue Driver Entry Point
+#
+ EdkIIGluePeimEntryPoint.c
+
+[includes.common]
+ .
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include/Library
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/CpuInit/Pei
+#
+# EDK II Glue Library utilizes some standard headers from EDK
+#
+ $(EFI_SOURCE)
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Pei/Include
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+ $(PLATFORM_ECP_PACKAGE)/Include
+ $(PLATFORM_ECP_PACKAGE)/Library/OpensslLib
+ $(PLATFORM_ECP_PACKAGE)/Library/PeiCryptLib
+
+[libraries.common]
+ $(PROJECT_PCH_FAMILY)PpiLib
+ EdkFrameworkPpiLib
+ EdkIIGlueBaseIoLibIntrinsic
+ EdkIIGlueBaseMemoryLib
+ EdkIIGluePeiDebugLibReportStatusCode
+ EdkIIGluePeiReportStatusCodeLib
+ EdkIIGluePeiServicesLib
+ EdkIIGluePeiMemoryAllocationLib
+ EdkPpiLib
+ CpuPpiLib
+ PlatformPolicyUpdatePeiLib
+ OpensslLib
+ PeiCryptLib
+ CpuPlatformLib
+
+[nmake.common]
+ IMAGE_ENTRY_POINT = _ModuleEntryPoint
+ DPX_SOURCE = CpuPolicyInitPei.dxs
+#
+# Module Entry Point
+#
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=CpuPolicyInitPeiEntryPoint
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ -D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ -D __EDKII_GLUE_PEI_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ -D __EDKII_GLUE_PEI_REPORT_STATUS_CODE_LIB__ \
+ -D __EDKII_GLUE_PEI_SERVICES_LIB__ \
+ -D __EDKII_GLUE_PEI_MEMORY_ALLOCATION_LIB__
diff --git a/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Pei/CpuPolicyPei.cif b/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Pei/CpuPolicyPei.cif
new file mode 100644
index 0000000..c241162
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Pei/CpuPolicyPei.cif
@@ -0,0 +1,13 @@
+<component>
+ name = "Cpu Policy PEI"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\SampleCode\CpuPolicyInit\Pei"
+ RefName = "Cpu Policy Pei"
+[files]
+"CpuPolicyPei.sdl"
+"CpuPolicyPei.mak"
+"CpuPolicyInitPei.c"
+"CpuPolicyInitPei.h"
+"CpuPolicyInitPei.dxs"
+"CpuPolicyInitPei.inf"
+<endComponent>
diff --git a/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Pei/CpuPolicyPei.mak b/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Pei/CpuPolicyPei.mak
new file mode 100644
index 0000000..3576f9e
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Pei/CpuPolicyPei.mak
@@ -0,0 +1,139 @@
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2010, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
+
+#**********************************************************************
+# $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/Intel Haswell Cpu RC PKG/Cpu Policy PEI/CpuPolicyPei.mak 5 7/02/12 7:23a Davidhsieh $
+#
+# $Revision: 5 $
+#
+# $Date: 7/02/12 7:23a $
+#**********************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/Intel Haswell Cpu RC PKG/Cpu Policy PEI/CpuPolicyPei.mak $
+#
+# 5 7/02/12 7:23a Davidhsieh
+#
+# 4 5/22/12 4:36a Davidhsieh
+# Add TXT_SUPPORT_FLAG define
+#
+# 3 5/14/12 2:20a Davidhsieh
+#
+# 2 2/23/12 2:46a Davidhsieh
+#
+# 1 2/07/12 3:56a Davidhsieh
+#
+# 2 9/21/11 11:22p Davidhsieh
+#
+# 1 5/06/11 6:06a Davidhsieh
+# First release
+#
+#**********************************************************************
+#<AMI_FHDR_START>
+#
+# Name:
+#
+# Description:
+#
+#<AMI_FHDR_END>
+#**********************************************************************
+EDK : CpuPolicyPei
+
+BUILD_CpuInitPei_DIR = $(BUILD_DIR)\$(CpuPolicyPei_DIR)
+
+$(BUILD_DIR)\CpuPolicyPei.mak : $(CpuPolicyPei_DIR)\CpuPolicyPei.cif $(BUILD_RULES)
+ $(CIF2MAK) $(CpuPolicyPei_DIR)\CpuPolicyPei.cif $(CIF2MAK_DEFAULTS)
+
+CpuPolicyPei : $(BUILD_DIR)\CpuPolicyPei.mak CpuPolicyPeiBin
+
+CpuPolicyPei_OBJECTS = \
+ $(BUILD_CpuInitPei_DIR)\CpuPolicyInitPei.obj
+
+CpuPolicyPei_MY_INCLUDES= \
+ $(EDK_INCLUDES) \
+ /I$(PROJECT_CPU_ROOT)\
+ /I$(PROJECT_CPU_ROOT)\Include \
+ /I$(PROJECT_CPU_ROOT)\Include\Library \
+ /I$(PROJECT_CPU_ROOT)\\Library \
+ /I$(CpuInitPei_DIR)
+
+CpuPolicyPei_DEFINES = $(MY_DEFINES)\
+ /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=CpuPolicyInitPeiEntryPoint"\
+ /D TXT_SUPPORT_FLAG=1 \
+ /D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ /D __EDKII_GLUE_BASE_LIB__ \
+ /D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ /D __EDKII_GLUE_PEI_SERVICES_TABLE_POINTER_LIB_MM7__ \
+ /D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ \
+
+
+CpuPolicyPei_LIBS =\
+ $(PchPlatformLib)\
+ $(EfiRuntimeLib_LIB)\
+ $(INTEL_PCH_PROTOCOL_LIB)\
+ $(EFIRUNTIMELIB)\
+ $(EDKFRAMEWORKPPILIB) \
+ $(CPUIA32LIB)\
+ $(EFIPROTOCOLLIB)\
+ $(EdkIIGlueDxeReportStatusCodeLib_LIB)\
+ $(EdkIIGluePeiDebugLibReportStatusCode_LIB)\
+ $(EdkIIGlueBaseLib_LIB)\
+ $(IntelPchPpiLib_LIB)\
+ $(EdkIIGlueBaseLibIA32_LIB)\
+ $(EdkIIGluePeiHobLib_LIB) \
+ $(CpuGuidLib_LIB) \
+ $(EdkIIGluePeiServicesLib_LIB) \
+ $(EdkIIGluePeiReportStatusCodeLib_LIB) \
+ $(PEIHOBLIB) \
+ $(EdkIIGlueDxeMemoryAllocationLib_LIB)\
+ $(EdkIIGlueBaseIoLibIntrinsic_LIB)\
+ $(EdkIIGlueUefiBootServicesTableLib_LIB)\
+ $(EdkIIGlueUefiDevicePathLib_LIB)\
+ $(EdkIIGlueBasePciLibPciExpress_LIB) \
+ $(EdkIIGlueBasePciExpressLib_LIB)\
+ $(CPU_PPI_LIB)\
+ $(PchPlatformPeiLib_LIB)\
+ $(CpuPlatformLib_LIB)\
+ $(EFISCRIPTLIB)
+
+CpuPolicyPeiBin : $(CpuPolicyPei_LIBS)
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\CpuPolicyPei.mak all\
+ NAME=CpuPolicyPei\
+ MAKEFILE=$(BUILD_DIR)\CpuPolicyPei.mak \
+ "MY_INCLUDES=$(CpuPolicyPei_MY_INCLUDES)" \
+ "MY_DEFINES=$(CpuPolicyPei_DEFINES)"\
+ OBJECTS="$(CpuPolicyPei_OBJECTS)" \
+ GUID=0ac2d35d-1c77-1033-a6f8-7ca55df7d0aa\
+ ENTRY_POINT=_ModuleEntryPoint \
+ TYPE=PEIM \
+ EDKIIModule=PEIM\
+ DEPEX1=$(CpuPolicyPei_DIR)\CpuPolicyInitPei.dxs \
+ DEPEX1_TYPE=EFI_SECTION_PEI_DEPEX \
+ COMPRESS=0
+
+#---------------------------------------------------------------------------
+#*************************************************************************
+#*************************************************************************
+#** **
+#** (C)Copyright 1985-2010, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+#** **
+#** Phone: (770)-246-8600 **
+#** **
+#*************************************************************************
+#*************************************************************************
diff --git a/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Pei/CpuPolicyPei.sdl b/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Pei/CpuPolicyPei.sdl
new file mode 100644
index 0000000..947bdb1
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/CpuPolicyInit/Pei/CpuPolicyPei.sdl
@@ -0,0 +1,58 @@
+#****************************************************************************
+#****************************************************************************
+#** **
+#** (C)Copyright 1985-2011, American Megatrends, Inc. **
+#** **
+#** All Rights Reserved. **
+#** **
+#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30071 **
+#** **
+#** Phone (770)-246-8600 **
+#** **
+#****************************************************************************
+#****************************************************************************
+#****************************************************************************
+# $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/Intel Haswell Cpu RC PKG/Cpu Policy PEI/CpuPolicyPei.sdl 1 2/07/12 3:56a Davidhsieh $
+#
+# $Revision: 1 $
+#
+# $Date: 2/07/12 3:56a $
+#
+#****************************************************************************
+# Revision History
+# ----------------
+# $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/Intel Haswell Cpu RC PKG/Cpu Policy PEI/CpuPolicyPei.sdl $
+#
+# 1 2/07/12 3:56a Davidhsieh
+#
+# 1 5/06/11 6:06a Davidhsieh
+# First release
+#
+#
+#****************************************************************************
+TOKEN
+ Name = "CpuPeiPolicySupport"
+ Value = "1"
+ Help = "Main switch to enable Cpu Policy Pei support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+End
+
+PATH
+ Name = "CpuPolicyPei_DIR"
+End
+
+MODULE
+ Help = "Includes CpuPeiPolicy.mak to Project"
+ File = "CpuPolicyPei.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\CpuPolicyPei.ffs"
+ Parent = "FV_BB"
+ InvokeOrder = AfterParent
+End
+
diff --git a/ReferenceCode/Haswell/SampleCode/CpuSampleCode.cif b/ReferenceCode/Haswell/SampleCode/CpuSampleCode.cif
new file mode 100644
index 0000000..886b397
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/CpuSampleCode.cif
@@ -0,0 +1,15 @@
+<component>
+ name = "CpuSampleCode"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\SampleCode\"
+ RefName = "CpuSampleCode"
+[files]
+"Include\AslUpdateLib.h"
+"Include\PeiKscLib.h"
+"Include\SmmIoLib.h"
+"Include\KscLib.h"
+"Include\acpibuild.dsc"
+"Include\Cpu.h"
+"Include\FlashMap.h"
+"Include\BootGuardRevocationLib.h"
+<endComponent>
diff --git a/ReferenceCode/Haswell/SampleCode/Include/AslUpdateLib.h b/ReferenceCode/Haswell/SampleCode/Include/AslUpdateLib.h
new file mode 100644
index 0000000..eb9d1cf
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Include/AslUpdateLib.h
@@ -0,0 +1,178 @@
+/** @file
+ ASL dynamic update library definitions.
+
+ This library provides dymanic update to various ASL structures.
+
+ There may be different libraries for different environments (PEI, BS, RT, SMM).
+ Make sure you meet the requirements for the library (protocol dependencies, use
+ restrictions, etc).
+
+@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
+**/
+#ifndef _ASL_UPDATE_LIB_H_
+#define _ASL_UPDATE_LIB_H_
+
+///
+/// Include files
+///
+#include "Tiano.h"
+#include "Acpi.h"
+#include "Acpi3_0.h"
+
+#include EFI_PROTOCOL_DEPENDENCY (AcpiSupport)
+#include EFI_PROTOCOL_DEPENDENCY (AcpiTable)
+
+///
+/// AML parsing definitions
+///
+#define AML_NAME_OP 0x08
+#define AML_BYTE_OP 0x0A
+#define AML_WORD_OP 0x0B
+#define AML_DWORD_OP 0x0C
+#define AML_QWORD_OP 0x0E
+#define AML_SCOPE_OP 0x10
+#define AML_BUFFER_OP 0x11
+#define AML_PACKAGE_OP 0x12
+#define AML_METHOD_OP 0x14
+#define AML_EXT_OP 0x5B
+#define AML_OPREGION_OP 0x80
+#define AML_DEVICE_OP 0x82
+#define AML_PROCESSOR_OP 0x83
+
+///
+/// Magic number definition for values to be updated
+///
+#define UINT16_BIT_MAGIC_NUMBER 0xFFFF
+#define UINT32_BIT_MAGIC_NUMBER 0xFFFFFFFF
+
+///
+/// ASL PSS package structure layout
+///
+#pragma pack(1)
+typedef struct {
+ UINT8 NameOp; ///< 12h ;First opcode is a NameOp.
+ UINT8 PackageLead; ///< 20h ;First opcode is a NameOp.
+ UINT8 NumEntries; ///< 06h ;First opcode is a NameOp.
+ UINT8 DwordPrefix1; ///< 0Ch
+ UINT32 CoreFrequency; ///< 00h
+ UINT8 DwordPrefix2; ///< 0Ch
+ UINT32 Power; ///< 00h
+ UINT8 DwordPrefix3; ///< 0Ch
+ UINT32 TransLatency; ///< 00h
+ UINT8 DwordPrefix4; ///< 0Ch
+ UINT32 BMLatency; ///< 00h
+ UINT8 DwordPrefix5; ///< 0Ch
+ UINT32 Control; ///< 00h
+ UINT8 DwordPrefix6; ///< 0Ch
+ UINT32 Status; ///< 00h
+} PSS_PACKAGE_LAYOUT;
+#pragma pack()
+
+/**
+ Initialize the ASL update library state.
+ This must be called prior to invoking other library functions.
+
+ @retval EFI_SUCCESS - The function completed successfully.
+**/
+EFI_STATUS
+InitializeAslUpdateLib (
+ VOID
+ );
+
+/**
+ This function locates an ACPI structure and updates it.
+ This function knows how to update operation regions and BUFA/BUFB resource structures.
+
+ This function may not be implemented in all instantiations of this library.
+
+ @param[in] AslSignature - The signature of Operation Region that we want to update.
+ @param[in] BaseAddress - Base address of IO trap.
+ @param[in] Length - Length of IO address.
+
+ @retval EFI_SUCCESS - The function completed successfully.
+**/
+EFI_STATUS
+UpdateAslCode (
+ IN UINT32 AslSignature,
+ IN UINT16 BaseAddress,
+ IN UINT8 Length
+ );
+
+/**
+ This function uses the ACPI support protocol to locate an ACPI table using the .
+ It is really only useful for finding tables that only have a single instance,
+ e.g. FADT, FACS, MADT, etc. It is not good for locating SSDT, etc.
+ Matches are determined by finding the table with ACPI table that has
+ a matching signature and version.
+
+ @param[in] TableId - Pointer to an ASCII string containing the Signature to match
+ @param[in] Table - Updated with a pointer to the table
+ @param[in] Handle - AcpiSupport protocol table handle for the table found
+ @param[in] Version - On input, the version of the table desired,
+ on output, the versions the table belongs to
+ (see AcpiSupport protocol for details)
+
+ @retval EFI_SUCCESS - The function completed successfully.
+**/
+EFI_STATUS
+LocateAcpiTableBySignature (
+ IN UINT32 Signature,
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER **Table,
+ IN OUT UINTN *Handle,
+ IN OUT EFI_ACPI_TABLE_VERSION *Version
+ );
+
+/**
+ This function uses the ACPI support protocol to locate an ACPI SSDT table.
+ The table is located by searching for a matching OEM Table ID field.
+ Partial match searches are supported via the TableIdSize parameter.
+
+ @param[in] TableId - Pointer to an ASCII string containing the OEM Table ID from the ACPI table header
+ @param[in] TableIdSize - Length of the TableId to match. Table ID are 8 bytes long, this function
+ will consider it a match if the first TableIdSize bytes match
+ @param[in] Table - Updated with a pointer to the table
+ @param[in] Handle - AcpiSupport protocol table handle for the table found
+ @param[in] Version - See AcpiSupport protocol, GetAcpiTable function for use
+
+ @retval EFI_SUCCESS - The function completed successfully.
+**/
+EFI_STATUS
+LocateAcpiTableByOemTableId (
+ IN UINT8 *TableId,
+ IN UINT8 TableIdSize,
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER **Table,
+ IN OUT UINTN *Handle,
+ IN OUT EFI_ACPI_TABLE_VERSION *Version
+ );
+
+/**
+ This function calculates and updates an UINT8 checksum.
+
+ @param[in] Buffer Pointer to buffer to checksum
+ @param[in] Size Number of bytes to checksum
+ @param[in] ChecksumOffset Offset to place the checksum result in
+
+ @retval EFI_SUCCESS The function completed successfully.
+**/
+EFI_STATUS
+EFI_BOOTSERVICE
+AcpiChecksum (
+ IN VOID *Buffer,
+ IN UINTN Size,
+ IN UINTN ChecksumOffset
+ );
+
+#endif
diff --git a/ReferenceCode/Haswell/SampleCode/Include/BootGuardRevocationLib.h b/ReferenceCode/Haswell/SampleCode/Include/BootGuardRevocationLib.h
new file mode 100644
index 0000000..f7d0fbc
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Include/BootGuardRevocationLib.h
@@ -0,0 +1,35 @@
+/** @file
+ Header file for Boot Guard revocation notification.
+
+@copyright
+ Copyright (c) 2012 - 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
+**/
+#ifndef _BOOT_GUARD_REVOCATION_LIB_H_
+#define _BOOT_GUARD_REVOCATION_LIB_H_
+
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#endif
+
+/**
+ Provide a hook for OEM to deal with Boot Guard revocation flow.
+**/
+VOID
+EFIAPI
+BootGuardOemRevocationHook (
+ VOID
+ );
+
+#endif
diff --git a/ReferenceCode/Haswell/SampleCode/Include/Cpu.h b/ReferenceCode/Haswell/SampleCode/Include/Cpu.h
new file mode 100644
index 0000000..94b7e56
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Include/Cpu.h
@@ -0,0 +1,63 @@
+/** @file
+ Various CPU-specific definitions.
+
+@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
+**/
+#ifndef _CPU_H_
+#define _CPU_H_
+
+#define B_FAMILY_MODEL_STEPPING 0x00000FFF
+
+#define EFI_MSR_IA32_PERF_STS 0x198
+#define EFI_MSR_IA32_PERF_CTL 0x199
+#define EFI_MSR_IA32_CLOCK_MODULATION 0x19A
+#define EFI_MSR_IA32_THERM_STATUS 0x19C
+
+#define B_BS_VID 0x0000003F
+#define N_BS_VID 0
+#define B_BS_RATIO 0x00001F00
+#define N_BS_RATIO 8
+
+///
+/// UINT64 workaround
+///
+/// The MS compiler doesn't handle QWORDs very well. I'm breaking
+/// them into DWORDs to circumvent the problems. Converting back
+/// shouldn't be a big deal.
+///
+#pragma pack(1)
+typedef union _MSR_REGISTER {
+ UINT64 Qword;
+
+ struct _DWORDS {
+ UINT32 Low;
+ UINT32 High;
+ } Dwords;
+
+ struct _BYTES {
+ UINT8 FirstByte;
+ UINT8 SecondByte;
+ UINT8 ThirdByte;
+ UINT8 FouthByte;
+ UINT8 FifthByte;
+ UINT8 SixthByte;
+ UINT8 SeventhByte;
+ UINT8 EighthByte;
+ } Bytes;
+
+} MSR_REGISTER;
+#pragma pack()
+#endif
diff --git a/ReferenceCode/Haswell/SampleCode/Include/FlashMap.h b/ReferenceCode/Haswell/SampleCode/Include/FlashMap.h
new file mode 100644
index 0000000..b72df34
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Include/FlashMap.h
@@ -0,0 +1,27 @@
+/** @file
+ File content auto-generated by FlashMap utility
+
+@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
+**/
+#ifndef _FLASH_MAP_H_
+#define _FLASH_MAP_H_
+
+///
+/// Please confirm following configuration from your platform setting.
+///
+#define FLASH_REGION_MICROCODE_SIZE 0xffd90000
+#define FLASH_REGION_MICROCODE_BASE 0x00040000
+#endif ///< #ifndef _FLASH_MAP_H_
diff --git a/ReferenceCode/Haswell/SampleCode/Include/KscLib.h b/ReferenceCode/Haswell/SampleCode/Include/KscLib.h
new file mode 100644
index 0000000..a428f77
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Include/KscLib.h
@@ -0,0 +1,232 @@
+/** @file
+ KSC library functions and definitions.
+
+ This library provides basic KSC interface. It is deemed simple enough and uses in
+ so few cases that there is not currently benefit to implementing a protocol.
+ If more consumers are added, it may be benefitial to implement as a protocol.
+
+ There may be different libraries for different environments (PEI, BS, RT, SMM).
+ Make sure you meet the requirements for the library (protocol dependencies, use
+ restrictions, etc).
+
+@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
+**/
+#ifndef _KSC_LIB_H_
+#define _KSC_LIB_H_
+
+///
+/// Include files
+///
+#include "Tiano.h"
+
+///
+/// Timeout if KSC command/data fails
+///
+#define KSC_TIME_OUT 0x20000
+
+///
+/// The Keyboard and System management Controller (KSC) implements a standard 8042 keyboard
+/// controller interface at ports 0x60/0x64 and a ACPI compliant system management controller
+/// at ports 0x62/0x66. Port 0x66 is the command and status port, port 0x62 is the data port.
+///
+#define KSC_D_PORT 0x62
+#define KSC_C_PORT 0x66
+
+///
+/// Status Port 0x62
+///
+#define KSC_S_OVR_TMP 0x80 ///< Current CPU temperature exceeds the threshold
+#define KSC_S_SMI_EVT 0x40 ///< SMI event is pending
+#define KSC_S_SCI_EVT 0x20 ///< SCI event is pending
+#define KSC_S_BURST 0x10 ///< KSC is in burst mode or normal mode
+#define KSC_S_CMD 0x08 ///< Byte in data register is command/data
+#define KSC_S_IGN 0x04 ///< Ignored
+#define KSC_S_IBF 0x02 ///< Input buffer is full/empty
+#define KSC_S_OBF 0x01 ///< Output buffer is full/empty
+///
+/// KSC commands that are issued to the KSC through the command port (0x66).
+/// New commands and command parameters should only be written by the host when IBF=0.
+/// Data read from the KSC data port is valid only when OBF=1.
+///
+#define KSC_C_SMI_NOTIFY_ENABLE 0x04 ///< Enable SMI notifications to the host
+#define KSC_C_SMI_NOTIFY_DISABLE 0x05 ///< SMI notifications are disabled and pending notifications cleared
+#define KSC_C_QUERY_SYS_STATUS 0x06 ///< Returns 1 byte of information about the system status
+#define KSC_B_SYS_STATUS_FAN 0x40 ///< Fan status (1 = ON)
+#define KSC_B_SYS_STATUS_DOCK 0x20 ///< Dock status (1 = Docked)
+#define KSC_B_SYS_STATUS_AC 0x10 ///< AC power (1 = AC powered)
+#define KSC_B_SYS_STATUS_THERMAL 0x0F ///< CPU thermal state (0 ~ 9)
+#define KSC_C_FAB_ID 0x0D ///< Get the board fab ID in the lower 3 bits
+#define KSC_C_SYSTEM_POWER_OFF 0x22 ///< Turn off the system power
+#define KSC_C_LAN_ON 0x46 ///< Turn on the power to LAN through EC/KSC
+#define KSC_C_LAN_OFF 0x47 ///< Turn off the power to LAN through EC/KSC
+#define KSC_C_GET_TEMP 0x50 ///< Returns the CPU temperature as read from the SMBus thermal sensor.
+#define KSC_C_SET_CTEMP 0x58 ///< The next byte written to the data port will be the shutdown temperature
+#define KSC_EC_PCH_SMBUS_EN 0x60 ///< EC PCH SMBus thermal monitoring Enable cmd
+#define KSC_EC_PCH_SMBUS_DIS 0x61 ///< EC PCH SMBus thermal monitoring Disable cmd
+#define KSC_TS_ON_DIMM_EN 0x6B ///< TS-on-DIMM thermal monitoring enable command
+#define KSC_TS_ON_DIMM_DIS 0x6C ///< TS-on-DIMM thermal monitoring disable command
+#define KSC_C_PCH_SMBUS_MSG_LENGTH 0x6D ///< PCH SMBus block read buffer length
+#define KSC_C_PCH_SMBUS_PEC_EN 0x6E ///< PCH SMBus Packet Error Checking (PEC) Enable command.
+#define KSC_C_PCH_SMBUS_PEC_DIS 0x76 ///< PCH SMBus Packet Error Checking (PEC) Disable command.
+#define KSC_C_EC_SMBUS_HIGH_SPEED 0x75 ///< EC SMBus high speed mode command
+#define KSC_EC_PCH_SMBUS_WRITE_EN 0x68 ///< EC PCH SMBus Write Enable cmd
+#define KSC_EC_PCH_SMBUS_WRITE_DIS 0x69 ///< EC PCH SMBus Write Disable cmd
+#define KSC_C_SMI_QUERY 0x70 ///< The host reads the data port to retrieve the notifications
+#define KSC_C_SMI_TIMER 0x71 ///< Commands the KSC to generate a periodic SMI to the host
+#define KSC_C_SMI_HOTKEY 0x72 ///< Get the scan code of hotkey pressed (CTRL + ALT + SHIFT + key)
+#define KSC_C_READ_MEM 0x80 ///< Read the KSC memory
+#define KSC_C_WRITE_MEM 0x81 ///< Write the KSC memory
+#define KSC_C_DOCK_STATUS 0x8A ///< Get the dock status
+#define KSC_B_DOCK_STATUS_ATTACH 0x01 ///< Dock status (1 = Attach)
+#define KSC_C_KSC_REVISION 0x90 ///< Get the revision for the KSC
+#define KSC_C_SMI_INJECT 0xBA ///< The next byte written to the data port will generate an immediate SMI
+#define KSC_C_SMI_DISABLE 0xBC ///< SMI generation by the KSC is disabled
+#define KSC_C_SMI_ENABLE 0xBD ///< SMI generation by the KSC is enabled
+#define KSC_C_ACPI_ENABLE 0xAA ///< Enable ACPI mode
+#define KSC_C_ACPI_DISABLE 0xAB ///< Disable ACPI mode
+///
+/// KSC commands that are only valid if the EC has ACPI mode enabled.
+/// Note that capacity and voltage are 16 bit values, thus you need to read them from
+/// ACPI space with two reads (little Endian).
+///
+#define KSC_VIRTUAL_BAT_STATUS 48 ///< Status of the virtual battery (present)
+#define KSC_VIRTUAL_BAT_PRESENT_MASK 0x10 ///< Bit 4 is the indicator
+#define KSC_REAL_BAT1_STATUS 50 ///< Status of the first real battery (present, charging)
+#define KSC_REAL_BAT1_REMAINING_CAPACITY 89 ///< Remaining capacity in mWh
+#define KSC_REAL_BAT1_RESOLUTION_VOLTAGE 93 ///< Full resolution voltage in mV
+#define KSC_REAL_BAT2_STATUS 54 ///< Status of the second real battery (present, charging)
+#define KSC_REAL_BAT2_REMAINING_CAPACITY 99 ///< Remaining capacity in mWh
+#define KSC_REAL_BAT2_RESOLUTION_VOLTAGE 103 ///< Full resolution voltage in mV
+#define KSC_REAL_BAT_PRESENT_MASK 0x8 ///< Bit 3 is the indicator
+#define KSC_REAL_BAT_CHARGING_MASK 0x1 ///< Bit 1 is the indicator
+///
+/// SMI notification code table, read through command KSC_C_SMI_QUERY
+///
+#define KSC_N_SMI_NULL 0x00 ///< Null marks the end of the SMI notification queue
+#define KSC_N_SMI_HOTKEY 0x20 ///< Hotkey pressed SMI
+#define KSC_N_SMI_ACINSERTION 0x30 ///< AC insertion SMI
+#define KSC_N_SMI_ACREMOVAL 0x31 ///< AC removal SMI
+#define KSC_N_SMI_PWRSW 0x32 ///< Power switch press SMI
+#define KSC_N_SMI_LID 0x33 ///< Lid switch change SMI
+#define KSC_N_SMI_VB 0x34 ///< Virtual battery switch change SMI
+#define KSC_N_SMI_THERM_0 0x60 ///< Thermal state 0 SMI
+#define KSC_N_SMI_THERM_1 0x61 ///< Thermal state 1 SMI
+#define KSC_N_SMI_THERM_2 0x62 ///< Thermal state 2 SMI
+#define KSC_N_SMI_THERM_3 0x63 ///< Thermal state 3 SMI
+#define KSC_N_SMI_THERM_4 0x64 ///< Thermal state 4 SMI
+#define KSC_N_SMI_THERM_5 0x65 ///< Thermal state 5 SMI
+#define KSC_N_SMI_THERM_6 0x66 ///< Thermal state 6 SMI
+#define KSC_N_SMI_THERM_7 0x67 ///< Thermal state 7 SMI
+#define KSC_N_SMI_THERM_8 0x68 ///< Thermal state 8 SMI
+#define KSC_N_SMI_DOCKED 0x70 ///< Dock complete SMI
+#define KSC_N_SMI_UNDOCKED 0x71 ///< Undock complete SMI
+#define KSC_N_SMI_UNDOCKREQUEST 0x72 ///< Undocking request SMI
+#define KSC_N_SMI_TIMER 0x80 ///< Timer wakeup SMI
+///
+/// Hotkey scan code (CTRL + ALT + SHIFT + key)
+///
+#define KSC_HK_ESC 0x01 ///< ESC
+#define KSC_HK_1 0x02 ///< 1 !
+#define KSC_HK_2 0x03 ///< 2 @
+#define KSC_HK_3 0x04 ///< 3 #
+#define KSC_HK_4 0x05 ///< 4 $
+#define KSC_HK_5 0x06 ///< 5 %
+#define KSC_HK_6 0x07 ///< 6 ^
+#define KSC_HK_7 0x08 ///< 7 &
+#define KSC_HK_8 0x09 ///< 8 *
+#define KSC_HK_9 0x0A ///< 9 (
+#define KSC_HK_0 0x0B ///< 0 )
+#define KSC_HK_MINUS 0x0C ///< - _
+#define KSC_HK_ADD 0x0D ///< = +
+#define KSC_HK_F1 0x3B ///< F1
+#define KSC_HK_F2 0x3C ///< F2
+#define KSC_HK_F3 0x3D ///< F3
+#define KSC_HK_F4 0x3E ///< F4
+#define KSC_HK_F5 0x3F ///< F5
+#define KSC_HK_F6 0x40 ///< F6
+#define KSC_HK_F7 0x41 ///< F7
+#define KSC_HK_F8 0x42 ///< F8
+#define KSC_HK_F9 0x43 ///< F9
+#define KSC_HK_F10 0x44 ///< F10
+#define KSC_HK_F11 0x57 ///< F11
+#define KSC_HK_F12 0x58 ///< F12
+///
+/// Function declarations
+///
+/**
+ This function initializes the KSC library.
+ It must be called before using any of the other KSC library functions.
+
+ @param[in] None.
+
+ @retval EFI_SUCCESS - KscLib is successfully initialized.
+**/
+EFI_STATUS
+InitializeKscLib (
+ VOID
+ );
+/**
+ Send a command to the Keyboard System Controller.
+
+ @param[in] Command - Command byte to send
+
+ @retval EFI_SUCCESS - Command success
+ @retval EFI_TIMEOUT - Command timeout
+ @retval Other - Command failed
+**/
+EFI_STATUS
+SendKscCommand (
+ UINT8 Command
+ );
+/**
+ Sends data to Keyboard System Controller.
+
+ @param[in] Data - Data byte to send
+
+ @retval EFI_SUCCESS - Success
+ @retval EFI_TIMEOUT - Timeout
+ @retval Other - Failed
+**/
+EFI_STATUS
+SendKscData (
+ UINT8 Data
+ );
+/**
+ Receives data from Keyboard System Controller.
+
+ @param[in] Data - Data byte received
+
+ @retval EFI_SUCCESS - Read success
+ @retval EFI_TIMEOUT - Read timeout
+ @retval Other - Read failed
+**/
+EFI_STATUS
+ReceiveKscData (
+ UINT8 *Data
+ );
+/**
+ Receives status from Keyboard System Controller.
+
+ @param[in] KscStatus - Status byte to receive
+
+ @retval EFI_SUCCESS - Success
+ @retval Other - Failed
+**/
+EFI_STATUS
+ReceiveKscStatus (
+ UINT8 *KscStatus
+ );
+#endif
diff --git a/ReferenceCode/Haswell/SampleCode/Include/PeiKscLib.h b/ReferenceCode/Haswell/SampleCode/Include/PeiKscLib.h
new file mode 100644
index 0000000..76c3dfa
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Include/PeiKscLib.h
@@ -0,0 +1,224 @@
+/** @file
+ KSC library functions and definitions.
+
+ This library provides basic KSC interface. It is deemed simple enough and uses in
+ so few cases that there is not currently benefit to implementing a protocol.
+ If more consumers are added, it may be benefitial to implement as a protocol.
+
+ There may be different libraries for different environments (PEI, BS, RT, SMM).
+ Make sure you meet the requirements for the library (protocol dependencies, use
+ restrictions, etc).
+
+@copyright
+ Copyright (c) 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
+**/
+#ifndef _PEI_KSC_LIB_H_
+#define _PEI_KSC_LIB_H_
+
+///
+/// Timeout if KSC command/data fails
+///
+#define KSC_TIME_OUT 0x20000
+
+///
+/// The Keyboard and System management Controller (KSC) implements a standard 8042 keyboard
+/// controller interface at ports 0x60/0x64 and a ACPI compliant system management controller
+/// at ports 0x62/0x66. Port 0x66 is the command and status port, port 0x62 is the data port.
+///
+#define KSC_D_PORT 0x62
+#define KSC_C_PORT 0x66
+
+///
+/// Status Port 0x62
+///
+#define KSC_S_OVR_TMP 0x80 ///< Current CPU temperature exceeds the threshold
+#define KSC_S_SMI_EVT 0x40 ///< SMI event is pending
+#define KSC_S_SCI_EVT 0x20 ///< SCI event is pending
+#define KSC_S_BURST 0x10 ///< KSC is in burst mode or normal mode
+#define KSC_S_CMD 0x08 ///< Byte in data register is command/data
+#define KSC_S_IGN 0x04 ///< Ignored
+#define KSC_S_IBF 0x02 ///< Input buffer is full/empty
+#define KSC_S_OBF 0x01 ///< Output buffer is full/empty
+
+///
+/// KSC commands that are issued to the KSC through the command port (0x66).
+/// New commands and command parameters should only be written by the host when IBF=0.
+/// Data read from the KSC data port is valid only when OBF=1.
+///
+#define KSC_C_SMI_NOTIFY_ENABLE 0x04 ///< Enable SMI notifications to the host
+#define KSC_C_SMI_NOTIFY_DISABLE 0x05 ///< SMI notifications are disabled and pending notifications cleared
+#define KSC_C_QUERY_SYS_STATUS 0x06 ///< Returns 1 byte of information about the system status
+#define KSC_B_SYS_STATUS_FAN 0x40 ///< Fan status (1 = ON)
+#define KSC_B_SYS_STATUS_DOCK 0x20 ///< Dock status (1 = Docked)
+#define KSC_B_SYS_STATUS_AC 0x10 ///< AC power (1 = AC powered)
+#define KSC_B_SYS_STATUS_THERMAL 0x0F ///< CPU thermal state (0 ~ 9)
+#define KSC_C_FAB_ID 0x0D ///< Get the board fab ID in the lower 3 bits
+#define KSC_B_BOARD_ID 0x0F ///< Board ID = [3:0]
+#define KSC_C_SYSTEM_POWER_OFF 0x22 ///< Turn off the system power
+#define KSC_C_LAN_ON 0x46 ///< Turn on the power to LAN through EC/KSC
+#define KSC_C_LAN_OFF 0x47 ///< Turn off the power to LAN through EC/KSC
+#define KSC_C_GET_DTEMP 0x50 ///< Returns the CPU temperature as read from the SMBus thermal sensor.
+#define KSC_C_SET_CTEMP 0x58 ///< The next byte written to the data port will be the shutdown temperature
+#define KSC_C_EN_DTEMP 0x5E ///< Commands KSC to begin reading Thermal Diode and comparing to Critical Temperature
+#define KSC_C_DIS_DTEMP 0x5F ///< Commands KSC to stop reading Thermal Diode
+#define KSC_C_SMI_QUERY 0x70 ///< The host reads the data port to retrieve the notifications
+#define KSC_C_SMI_TIMER 0x71 ///< Commands the KSC to generate a periodic SMI to the host
+#define KSC_C_SMI_HOTKEY 0x72 ///< Get the scan code of hotkey pressed (CTRL + ALT + SHIFT + key)
+#define KSC_C_READ_MEM 0x80 ///< Read the KSC memory
+#define KSC_C_WRITE_MEM 0x81 ///< Write the KSC memory
+#define KSC_C_KSC_REVISION 0x90 ///< Get the revision for the KSC
+#define KSC_C_SMI_INJECT 0xBA ///< The next byte written to the data port will generate an immediate SMI
+#define KSC_C_SMI_DISABLE 0xBC ///< SMI generation by the KSC is disabled
+#define KSC_C_SMI_ENABLE 0xBD ///< SMI generation by the KSC is enabled
+#define KSC_C_ACPI_ENABLE 0xAA ///< Enable ACPI mode
+#define KSC_C_ACPI_DISABLE 0xAB ///< Disable ACPI mode
+
+///
+/// SMI notification code table, read through command KSC_C_SMI_QUERY
+///
+#define KSC_N_SMI_NULL 0x00 ///< Null marks the end of the SMI notification queue
+#define KSC_N_SMI_HOTKEY 0x20 ///< Hotkey pressed SMI
+#define KSC_N_SMI_ACINSERTION 0x30 ///< AC insertion SMI
+#define KSC_N_SMI_ACREMOVAL 0x31 ///< AC removal SMI
+#define KSC_N_SMI_PWRSW 0x32 ///< Power switch press SMI
+#define KSC_N_SMI_LID 0x33 ///< Lid switch change SMI
+#define KSC_N_SMI_VB 0x34 ///< Virtual battery switch change SMI
+#define KSC_N_SMI_THERM_0 0x60 ///< Thermal state 0 SMI
+#define KSC_N_SMI_THERM_1 0x61 ///< Thermal state 1 SMI
+#define KSC_N_SMI_THERM_2 0x62 ///< Thermal state 2 SMI
+#define KSC_N_SMI_THERM_3 0x63 ///< Thermal state 3 SMI
+#define KSC_N_SMI_THERM_4 0x64 ///< Thermal state 4 SMI
+#define KSC_N_SMI_THERM_5 0x65 ///< Thermal state 5 SMI
+#define KSC_N_SMI_THERM_6 0x66 ///< Thermal state 6 SMI
+#define KSC_N_SMI_THERM_7 0x67 ///< Thermal state 7 SMI
+#define KSC_N_SMI_THERM_8 0x68 ///< Thermal state 8 SMI
+#define KSC_N_SMI_DOCKED 0x70 ///< Dock complete SMI
+#define KSC_N_SMI_UNDOCKED 0x71 ///< Undock complete SMI
+#define KSC_N_SMI_UNDOCKREQUEST 0x72 ///< Undocking request SMI
+#define KSC_N_SMI_TIMER 0x80 ///< Timer wakeup SMI
+
+///
+/// Hotkey scan code (CTRL + ALT + SHIFT + key)
+///
+#define KSC_HK_ESC 0x01 ///< ESC
+#define KSC_HK_1 0x02 ///< 1 !
+#define KSC_HK_2 0x03 ///< 2 @
+#define KSC_HK_3 0x04 ///< 3 #
+#define KSC_HK_4 0x05 ///< 4 $
+#define KSC_HK_5 0x06 ///< 5 %
+#define KSC_HK_6 0x07 ///< 6 ^
+#define KSC_HK_7 0x08 ///< 7 &
+#define KSC_HK_8 0x09 ///< 8 *
+#define KSC_HK_9 0x0A ///< 9 (
+#define KSC_HK_0 0x0B ///< 0 )
+#define KSC_HK_MINUS 0x0C ///< - _
+#define KSC_HK_ADD 0x0D ///< = +
+#define KSC_HK_F1 0x3B ///< F1
+#define KSC_HK_F2 0x3C ///< F2
+#define KSC_HK_F3 0x3D ///< F3
+#define KSC_HK_F4 0x3E ///< F4
+#define KSC_HK_F5 0x3F ///< F5
+#define KSC_HK_F6 0x40 ///< F6
+#define KSC_HK_F7 0x41 ///< F7
+#define KSC_HK_F8 0x42 ///< F8
+#define KSC_HK_F9 0x43 ///< F9
+#define KSC_HK_F10 0x44 ///< F10
+#define KSC_HK_F11 0x57 ///< F11
+#define KSC_HK_F12 0x58 ///< F12
+
+#include EFI_PPI_DEPENDENCY (CpuIo)
+#include EFI_PPI_DEPENDENCY (Stall)
+
+///
+/// Function declarations
+///
+EFI_STATUS
+SendKscCommand (
+ EFI_PEI_SERVICES **PeiServices,
+ PEI_CPU_IO_PPI *CpuIo,
+ PEI_STALL_PPI *StallPpi,
+ UINT8 Command
+ );
+/**
+ Sends command to Keyboard System Controller.
+
+ @param[in] PeiServices - PEI Services
+ @param[in] CpiIo - Pointer to CPU IO protocol
+ @param[in] StallPpi - Pointer to Stall PPI
+ @param[in] Command - Command byte to send
+
+ @retval EFI_SUCCESS - Command success
+ @retval EFI_DEVICE_ERROR - Command error
+ @retval EFI_TIMEOUT - Command timeout
+**/
+
+EFI_STATUS
+SendKscData (
+ EFI_PEI_SERVICES **PeiServices,
+ PEI_CPU_IO_PPI *CpuIo,
+ PEI_STALL_PPI *StallPpi,
+ UINT8 Data
+ );
+/**
+ Sends data to Keyboard System Controller.
+
+ @param[in] PeiServices - PEI Services
+ @param[in] CpiIo - Pointer to CPU IO protocol
+ @param[in] StallPpi - Pointer to Stall PPI
+ @param[in] Data - Data byte to send
+
+ @retval EFI_SUCCESS - Success
+ @retval EFI_DEVICE_ERROR - Error
+ @retval EFI_TIMEOUT - Command timeout
+**/
+
+EFI_STATUS
+ReceiveKscData (
+ EFI_PEI_SERVICES **PeiServices,
+ PEI_CPU_IO_PPI *CpuIo,
+ PEI_STALL_PPI *StallPpi,
+ UINT8 *Data
+ );
+/**
+ Receives data from Keyboard System Controller.
+
+ @param[in] PeiServices - PEI Services
+ @param[in] CpiIo - Pointer to CPU IO protocol
+ @param[in] StallPpi - Pointer to Stall PPI
+ @param[in] Data - Data byte received
+
+ @retval EFI_SUCCESS - Read success
+ @retval EFI_DEVICE_ERROR - Read error
+ @retval EFI_TIMEOUT - Command timeout
+**/
+
+EFI_STATUS
+ReceiveKscStatus (
+ EFI_PEI_SERVICES **PeiServices,
+ PEI_CPU_IO_PPI *CpuIo,
+ UINT8 *KscStatus
+ );
+/**
+ Receives status from Keyboard System Controller.
+
+ @param[in] PeiServices - PEI Services
+ @param[in] CpiIo - Pointer to CPU IO protocol
+ @param[in] KscStatus - Status byte to receive
+
+ @retval EFI_DEVICE_ERROR - Ksc library has not initialized yet or KSC not present
+ @retval EFI_SUCCESS - Get KSC status successfully
+**/
+
+#endif
diff --git a/ReferenceCode/Haswell/SampleCode/Include/SmmIoLib.h b/ReferenceCode/Haswell/SampleCode/Include/SmmIoLib.h
new file mode 100644
index 0000000..cc9eee9
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Include/SmmIoLib.h
@@ -0,0 +1,265 @@
+/** @file
+ This library provides SMM functions for IO and PCI IO access.
+ These can be used to save size and simplify code.
+ All contents must be runtime and SMM safe.
+
+@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
+**/
+#ifndef _SMM_IO_LIB_H_
+#define _SMM_IO_LIB_H_
+
+#include "EdkIIGlueDxe.h"
+#include "Pci22.h"
+
+///
+/// Utility consumed protocols
+///
+#include EFI_PROTOCOL_DEFINITION (SmmBase)
+
+///
+/// Global variables that must be defined and initialized to use this library
+///
+extern EFI_SMM_SYSTEM_TABLE *mSmst;
+
+///
+/// Definitions
+///
+#define ICH_ACPI_TIMER_MAX_VALUE 0x1000000 ///< The timer is 24 bit overflow
+///
+/// Pci I/O related data structure deifinition
+///
+typedef enum {
+ SmmPciWidthUint8 = 0,
+ SmmPciWidthUint16 = 1,
+ SmmPciWidthUint32 = 2,
+ SmmPciWidthUint64 = 3,
+ SmmPciWidthMaximum
+} SMM_PCI_IO_WIDTH;
+
+#define SMM_PCI_ADDRESS(bus, dev, func, reg) \
+ ((UINT64) ((((UINT32) bus) << 24) + (((UINT32) dev) << 16) + (((UINT32) func) << 8) + ((UINT32) reg)))
+
+typedef struct {
+ UINT8 Register;
+ UINT8 Function;
+ UINT8 Device;
+ UINT8 Bus;
+ UINT32 ExtendedRegister;
+} SMM_PCI_IO_ADDRESS;
+
+///
+/// CPU I/O Access Functions
+///
+/**
+ Do a one byte IO read
+
+ @param[in] Address - IO address to read
+
+ @retval Data read
+**/
+UINT8
+SmmIoRead8 (
+ IN UINT16 Address
+ );
+
+/**
+ Do a one byte IO write
+
+ @param[in] Address - IO address to write
+ @param[in] Data - Data to write
+**/
+VOID
+SmmIoWrite8 (
+ IN UINT16 Address,
+ IN UINT8 Data
+ );
+
+/**
+ Do a two byte IO read
+
+ @param[in] Address - IO address to read
+
+ @retval Data read
+**/
+UINT16
+SmmIoRead16 (
+ IN UINT16 Address
+ );
+
+/**
+ Do a two byte IO write
+
+ @param[in] Address - IO address to write
+ @param[in] Data - Data to write
+**/
+VOID
+SmmIoWrite16 (
+ IN UINT16 Address,
+ IN UINT16 Data
+ );
+
+/**
+ Do a four byte IO read
+
+ @param[in] Address - IO address to read
+
+ @retval Data read
+**/
+UINT32
+SmmIoRead32 (
+ IN UINT16 Address
+ );
+
+/**
+ Do a four byte IO write
+
+ @param[in] Address - IO address to write
+ @param[in] Data - Data to write
+**/
+VOID
+SmmIoWrite32 (
+ IN UINT16 Address,
+ IN UINT32 Data
+ );
+
+/**
+ Do a one byte Memory write
+
+ @param[in] Dest - Memory address to write
+ @param[in] Data - Data to write
+
+ @retval None
+**/
+VOID
+SmmMemWrite8 (
+ IN UINT64 Dest,
+ IN UINT8 Data
+ );
+
+/**
+ Do a one byte Memory read
+
+ @param[in] Dest - Memory address to read
+
+ @retval Data read
+**/
+UINT8
+SmmMemRead8 (
+ IN UINT64 Dest
+ );
+
+/**
+ Do a two bytes Memory write
+
+ @param[in] Dest - Memory address to write
+ @param[in] Data - Data to write
+
+ @retval None
+**/
+VOID
+SmmMemWrite16 (
+ IN UINT64 Dest,
+ IN UINT16 Data
+ );
+
+/**
+ Do a two bytes Memory read
+
+ @param[in] Dest - Memory address to read
+
+ @retval Data read
+**/
+UINT16
+SmmMemRead16 (
+ IN UINT64 Dest
+ );
+
+/**
+ Do a four bytes Memory write
+
+ @param[in] Dest - Memory address to write
+ @param[in] Data - Data to write
+
+ @retval None
+**/
+VOID
+SmmMemWrite32 (
+ IN UINT64 Dest,
+ IN UINT32 Data
+ );
+
+/**
+ Do a four bytes Memory read
+
+ @param[in] Dest - Memory address to read
+
+ @retval Data read
+**/
+UINT32
+SmmMemRead32 (
+ IN UINT64 Dest
+ );
+
+/**
+ Do a four bytes Memory read, then AND with Data, then write back to the same address
+
+ @param[in] Dest - Memory address to write
+ @param[in] Data - Data to do AND
+
+ @retval None
+**/
+VOID
+SmmMemAnd32 (
+ IN UINT64 Dest,
+ IN UINT32 Data
+ );
+///
+/// Pci Configuration Space access functions definition
+///
+/**
+ Read value from the specified PCI config space register
+
+ @param[in] Width - The width (8, 16 or 32 bits) of accessed pci config space register
+ @param[in] Address - The address of the accessed pci register (bus, dev, func, offset)
+ @param[in] Buffer - The returned value
+
+ @retval EFI_SUCCESS - All operations successfully
+ @retval EFI_INVALID_PARAMETER - Width is not valid or dosn't match register address
+ @retval Other error code - If any error occured when calling libiary functions
+**/
+EFI_STATUS
+SmmPciCfgRead (
+ IN SMM_PCI_IO_WIDTH Width,
+ IN SMM_PCI_IO_ADDRESS *Address,
+ IN OUT VOID *Buffer
+ );
+/**
+ Write value into the specified PCI config space register
+
+ @param[in] Width - The width (8, 16 or 32 bits) of accessed pci config space register
+ @param[in] Address - The address of the accessed pci register (bus, dev, func, offset)
+ @param[in] Buffer - The returned value
+
+ @retval EFI_SUCCESS - All operations successfully
+ @retval EFI_INVALID_PARAMETER - Width is not valid or dosn't match register address
+ @retval Other error code - If any error occured when calling libiary functions
+**/
+EFI_STATUS
+SmmPciCfgWrite (
+ IN SMM_PCI_IO_WIDTH Width,
+ IN SMM_PCI_IO_ADDRESS *Address,
+ IN OUT VOID *Buffer
+ );
+#endif
diff --git a/ReferenceCode/Haswell/SampleCode/Include/acpibuild.dsc b/ReferenceCode/Haswell/SampleCode/Include/acpibuild.dsc
new file mode 100644
index 0000000..cc3fb3d
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Include/acpibuild.dsc
@@ -0,0 +1,96 @@
+## @file
+# Build description file for building ASL and ACT file types used in ACPI tables
+# You should not put platform details, like how to build DSDT, SSDT, or how to
+# package the ACPI tables into a data file in this build. This should be platform
+# neutral code only.
+#
+#@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
+#
+
+[=============================================================================]
+[Compile.Ia32.act,Compile.x64.act]
+#
+# Instructions to create ACPI table sections out of ACPI table C source files.
+#
+
+#/*++
+#
+# If it already exists, then include the dependency list file for this
+# source file. If it doesn't exist, then this is a clean build and the
+# dependency file will get created below and the source file will get
+# compiled. Don't do any of this if NO_MAKEDEPS is defined.
+#
+#--*/
+!IF ("$(NO_MAKEDEPS)" == "")
+
+!IF EXIST($(DEST_DIR)\$(FILE).dep)
+!INCLUDE $(DEST_DIR)\$(FILE).dep
+!ENDIF
+
+#
+# This is how to create the dependency file.
+#
+DEP_FILE = $(DEST_DIR)\$(FILE).dep
+
+$(DEP_FILE) : $(SOURCE_FILE_NAME)
+ $(MAKEDEPS) -ignorenotfound -f $(SOURCE_FILE_NAME) -q -target \
+ $(DEST_DIR)\$(FILE).obj \
+ -o $(DEP_FILE) $(INC)
+
+!ENDIF
+
+#
+# Compile the file
+#
+$(DEST_DIR)\$(FILE).obj : $(SOURCE_FILE_NAME) $(INC_DEPS) $(DEP_FILE)
+ $(CC) $(C_FLAGS) /TC $(SOURCE_FILE_NAME)
+
+#
+# Link it
+#
+$(DEST_DIR)\$(FILE).exe : $(DEST_DIR)\$(FILE).obj
+ $(LINK) $(LINK_FLAGS_EXE) $(DEST_DIR)\$(FILE).obj /OUT:$(DEST_DIR)\$(FILE).exe /ENTRY:main
+
+#
+# Strip out the ACPI table
+#
+$(DEST_DIR)\$(FILE).acpi : $(DEST_DIR)\$(FILE).exe
+ $(GENACPITABLE) $(DEST_DIR)\$(FILE).exe $(DEST_DIR)\$(FILE).acpi
+
+#
+# Create a section from the ACPI table
+#
+$(DEST_DIR)\$(FILE).sec : $(DEST_DIR)\$(FILE).acpi
+ $(GENSECTION) -I $(DEST_DIR)\$(FILE).acpi -O $(DEST_DIR)\$(FILE).sec -S EFI_SECTION_RAW
+
+#
+# Add it to the targets to build
+#
+SECTIONS = $(SECTIONS) $(DEST_DIR)\$(FILE).sec
+
+[=============================================================================]
+[Compile.Ia32.asl,Compile.x64.asl]
+#
+# We run the ASL through the C Preprocessor to resolve definitions.
+#
+$(DEST_DIR)\$(FILE).asl : $(SOURCE_FILE_NAME)
+ $(CC) $(ASL_CPP_FLAGS) /nologo /C /EP /TC $(INC) -oa $(SOURCE_FILE_NAME) > $(DEST_DIR)\$(FILE).asl
+
+#
+# Add it to the targets to build
+#
+ASL_FILES = $(ASL_FILES) $(DEST_DIR)\$(FILE).asl
+
diff --git a/ReferenceCode/Haswell/SampleCode/Library/AslUpdate/Dxe/DxeAslUpdateLib.c b/ReferenceCode/Haswell/SampleCode/Library/AslUpdate/Dxe/DxeAslUpdateLib.c
new file mode 100644
index 0000000..8adbe64
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/AslUpdate/Dxe/DxeAslUpdateLib.c
@@ -0,0 +1,333 @@
+/** @file
+ Boot service DXE ASL update library implementation.
+
+ These functions in this file can be called during DXE and cannot be called during runtime
+ or in SMM which should use a RT or SMM library.
+
+ This library uses the ACPI Support protocol.
+
+@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
+
+**/
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "AslUpdateLib.h"
+#endif
+///
+/// Function implemenations
+///
+static EFI_ACPI_SUPPORT_PROTOCOL *mAcpiSupport = NULL;
+static EFI_ACPI_TABLE_PROTOCOL *mAcpiTable = NULL;
+
+/**
+ Initialize the ASL update library state.
+ This must be called prior to invoking other library functions.
+
+ @retval EFI_SUCCESS - The function completed successfully.
+**/
+EFI_STATUS
+InitializeAslUpdateLib (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ ///
+ /// Locate ACPI tables
+ ///
+ Status = gBS->LocateProtocol (&gEfiAcpiSupportGuid, NULL, (VOID **) &mAcpiSupport);
+ ASSERT_EFI_ERROR (Status);
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &mAcpiTable);
+ return EFI_SUCCESS;
+}
+
+/**
+ This procedure will update two kinds of asl code.
+ 1: Operating Region base address and length.
+ 2: Resource Consumption structures in device LDRC.
+
+ @param[in] AslSignature - The signature of Operation Region that we want to update.
+ @param[in] BaseAddress - Base address of IO trap.
+ @param[in] Length - Length of IO address.
+
+ @retval EFI_SUCCESS - The function completed successfully.
+**/
+EFI_STATUS
+UpdateAslCode (
+ IN UINT32 AslSignature,
+ IN UINT16 BaseAddress,
+ IN UINT8 Length
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_DESCRIPTION_HEADER *Table;
+ EFI_ACPI_TABLE_VERSION Version;
+ UINT8 *CurrPtr;
+ UINT8 *Operation;
+ UINT32 *Signature;
+ UINT8 *DsdtPointer;
+ INTN Index;
+ UINTN Handle;
+ UINT16 AslLength;
+
+ ///
+ /// Locate table with matching ID
+ ///
+ Index = 0;
+ AslLength = 0;
+ do {
+ Status = mAcpiSupport->GetAcpiTable (mAcpiSupport, Index, (VOID **) &Table, &Version, &Handle);
+ if (Status == EFI_NOT_FOUND) {
+ break;
+ }
+
+ ASSERT_EFI_ERROR (Status);
+ Index++;
+ } while (Table->Signature != EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE);
+
+ ///
+ /// Fix up the following ASL Code in DSDT:
+ /// (1) OperationRegion's IO Base Address and Length.
+ /// (2) Resource Consumption in LPC Device.
+ ///
+ CurrPtr = (UINT8 *) Table;
+
+ ///
+ /// Loop through the ASL looking for values that we must fix up.
+ ///
+ for (DsdtPointer = CurrPtr; DsdtPointer <= (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length); DsdtPointer++) {
+ ///
+ /// Get a pointer to compare for signature
+ ///
+ Signature = (UINT32 *) DsdtPointer;
+
+ ///
+ /// Check if this is the signature we are looking for
+ ///
+ if ((*Signature) == AslSignature) {
+ ///
+ /// Conditional match. For Region Objects, the Operator will always be the
+ /// byte immediately before the specific name. Therefore, subtract 1 to check
+ /// the Operator.
+ ///
+ Operation = DsdtPointer - 1;
+
+ ///
+ /// If we have an operation region, update the base address and length
+ ///
+ if (*Operation == AML_OPREGION_OP) {
+ ///
+ /// Fixup the Base Address in OperationRegion.
+ ///
+ *(UINT16 *) (DsdtPointer + 6) = BaseAddress;
+
+ ///
+ /// Fixup the Length in OperationRegion.
+ ///
+ *(DsdtPointer + 9) = Length;
+ }
+
+ } else if ((*Signature) == EFI_SIGNATURE_32 ('L', 'D', 'R', 'C')) {
+ ///
+ /// Make sure it's device of LDRC and read the length
+ ///
+ if (*(DsdtPointer - 2) == AML_DEVICE_OP) {
+ AslLength = *(DsdtPointer - 1);
+ } else if (*(DsdtPointer - 3) == AML_DEVICE_OP) {
+ AslLength = *(UINT16 *) (DsdtPointer - 2);
+ AslLength = (AslLength & 0x0F) + ((AslLength & 0x0FF00) >> 4);
+ }
+ ///
+ /// Conditional match. Search _CSR in Device (LDRC).
+ ///
+ for (Operation = DsdtPointer; Operation <= DsdtPointer + AslLength; Operation++) {
+ ///
+ /// Get a pointer to compare for signature
+ ///
+ Signature = (UINT32 *) Operation;
+
+ ///
+ /// Check if this is the signature we are looking for
+ ///
+ if ((*Signature) == EFI_SIGNATURE_32 ('_', 'C', 'R', 'S')) {
+ ///
+ /// Now look for an empty resource entry, fix the base address and length fields
+ ///
+ for (Index = 0; *(UINT16 *) (Operation + 9 + 8 * Index) != 0x0079; Index++) {
+ if (*(UINT16 *) (Operation + 11 + 8 * Index) == UINT16_BIT_MAGIC_NUMBER) {
+ ///
+ /// Fixup the Base Address and Length.
+ ///
+ *(UINT16 *) (Operation + 11 + 8 * Index) = BaseAddress;
+ *(UINT16 *) (Operation + 13 + 8 * Index) = BaseAddress;
+ *(Operation + 16 + 8 * Index) = Length;
+
+ break;
+ }
+ }
+ }
+ }
+
+ DsdtPointer = DsdtPointer + AslLength;
+ }
+ }
+ ///
+ /// Update the modified ACPI table
+ ///
+ Status = mAcpiTable->InstallAcpiTable (
+ mAcpiTable,
+ Table,
+ Table->Length,
+ &Handle
+ );
+ FreePool (Table);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function uses the ACPI support protocol to locate an ACPI table.
+ It is really only useful for finding tables that only have a single instance,
+ e.g. FADT, FACS, MADT, etc. It is not good for locating SSDT, etc.
+
+ @param[in] Signature - Pointer to an ASCII string containing the OEM Table ID from the ACPI table header
+ @param[in] Table - Updated with a pointer to the table
+ @param[in] Handle - AcpiSupport protocol table handle for the table found
+ @param[in] Version - The version of the table desired
+
+ @retval EFI_SUCCESS - The function completed successfully.
+**/
+EFI_STATUS
+LocateAcpiTableBySignature (
+ IN UINT32 Signature,
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER **Table,
+ IN OUT UINTN *Handle,
+ IN OUT EFI_ACPI_TABLE_VERSION *Version
+ )
+{
+ EFI_STATUS Status;
+ INTN Index;
+ EFI_ACPI_TABLE_VERSION DesiredVersion;
+
+ DesiredVersion = *Version;
+ ///
+ /// Locate table with matching ID
+ ///
+ Index = 0;
+ do {
+ Status = mAcpiSupport->GetAcpiTable (mAcpiSupport, Index, (VOID **) Table, Version, Handle);
+ if (Status == EFI_NOT_FOUND) {
+ break;
+ }
+
+ ASSERT_EFI_ERROR (Status);
+ Index++;
+ } while ((*Table)->Signature != Signature || !(*Version & DesiredVersion));
+
+ ///
+ /// If we found the table, there will be no error.
+ ///
+ return Status;
+}
+
+/**
+ This function uses the ACPI support protocol to locate an ACPI SSDT table.
+
+ @param[in] TableId - Pointer to an ASCII string containing the OEM Table ID from the ACPI table header
+ @param[in] TableIdSize - Length of the TableId to match. Table ID are 8 bytes long, this function
+ will consider it a match if the first TableIdSize bytes match
+ @param[in] Table - Updated with a pointer to the table
+ @param[in] Handle - AcpiSupport protocol table handle for the table found
+ @param[in] Version - See AcpiSupport protocol, GetAcpiTable function for use
+
+ @retval EFI_SUCCESS - The function completed successfully.
+**/
+EFI_STATUS
+LocateAcpiTableByOemTableId (
+ IN UINT8 *TableId,
+ IN UINT8 TableIdSize,
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER **Table,
+ IN OUT UINTN *Handle,
+ IN OUT EFI_ACPI_TABLE_VERSION *Version
+ )
+{
+ EFI_STATUS Status;
+ INTN Index;
+
+ ///
+ /// Locate table with matching ID
+ ///
+ Index = 0;
+ do {
+ Status = mAcpiSupport->GetAcpiTable (mAcpiSupport, Index, (VOID **) Table, Version, Handle);
+ if (Status == EFI_NOT_FOUND) {
+ break;
+ }
+
+ ASSERT_EFI_ERROR (Status);
+ Index++;
+ } while (CompareMem (&(*Table)->OemTableId, TableId, TableIdSize));
+
+ ///
+ /// If we found the table, there will be no error.
+ ///
+ return Status;
+}
+
+/**
+ This function calculates and updates an UINT8 checksum.
+
+ @param[in] Buffer Pointer to buffer to checksum
+ @param[in] Size Number of bytes to checksum
+ @param[in] ChecksumOffset Offset to place the checksum result in
+
+ @retval EFI_SUCCESS The function completed successfully.
+**/
+EFI_STATUS
+AcpiChecksum (
+ IN VOID *Buffer,
+ IN UINTN Size,
+ IN UINTN ChecksumOffset
+ )
+{
+ UINT8 Sum;
+ UINT8 *Ptr;
+
+ Sum = 0;
+ ///
+ /// Initialize pointer
+ ///
+ Ptr = Buffer;
+
+ ///
+ /// set checksum to 0 first
+ ///
+ Ptr[ChecksumOffset] = 0;
+
+ ///
+ /// add all content of buffer
+ ///
+ while (Size--) {
+ Sum = (UINT8) (Sum + (*Ptr++));
+ }
+ ///
+ /// set checksum
+ ///
+ Ptr = Buffer;
+ Ptr[ChecksumOffset] = (UINT8) (0xff - Sum + 1);
+
+ return EFI_SUCCESS;
+}
diff --git a/ReferenceCode/Haswell/SampleCode/Library/AslUpdate/Dxe/DxeAslUpdateLib.inf b/ReferenceCode/Haswell/SampleCode/Library/AslUpdate/Dxe/DxeAslUpdateLib.inf
new file mode 100644
index 0000000..138e053
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/AslUpdate/Dxe/DxeAslUpdateLib.inf
@@ -0,0 +1,46 @@
+## @file
+# Component description file.
+#
+#@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
+#
+
+[defines]
+BASE_NAME = DxeAslUpdateLib
+COMPONENT_TYPE = LIBRARY
+
+[sources.common]
+ DxeAslUpdateLib.c
+
+[includes.common]
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EFI_SOURCE)/Framework
+ .
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EFI_SOURCE)
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+ $(EDK_SOURCE)/Foundation
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/SampleCode/Include
+
+[libraries.common]
+ EdkFrameworkProtocolLib
+
+[nmake.common]
diff --git a/ReferenceCode/Haswell/SampleCode/Library/AslUpdate/Dxe/PpmAslUpdateLib.cif b/ReferenceCode/Haswell/SampleCode/Library/AslUpdate/Dxe/PpmAslUpdateLib.cif
new file mode 100644
index 0000000..5cfa2b1
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/AslUpdate/Dxe/PpmAslUpdateLib.cif
@@ -0,0 +1,11 @@
+<component>
+ name = "PpmAslUpdateLib"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\SampleCode\Library\AslUpdate\Dxe"
+ RefName = "PpmAslUpdateLib"
+[files]
+"PpmAslUpdateLib.sdl"
+"PpmAslUpdateLib.mak"
+"DxeAslUpdateLib.c"
+"DxeAslUpdateLib.inf"
+<endComponent>
diff --git a/ReferenceCode/Haswell/SampleCode/Library/AslUpdate/Dxe/PpmAslUpdateLib.mak b/ReferenceCode/Haswell/SampleCode/Library/AslUpdate/Dxe/PpmAslUpdateLib.mak
new file mode 100644
index 0000000..adcce28
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/AslUpdate/Dxe/PpmAslUpdateLib.mak
@@ -0,0 +1,31 @@
+# MAK file for the ModulePart:AslUpdateLib
+all : PpmAslUpdateLib
+
+$(BUILD_DIR)\PpmAslUpdateLib.lib : PpmAslUpdateLib
+
+PpmAslUpdateLib : $(BUILD_DIR)\PpmAslUpdateLib.mak PpmAslUpdateLibBin
+
+$(BUILD_DIR)\PpmAslUpdateLib.mak : $(PpmAslUpdateLib_DIR)\$(@B).cif $(PpmAslUpdateLib_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(PpmAslUpdateLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+PpmAslUpdateLib_INCLUDES=\
+ $(PROJECT_CPU_INCLUDES)\
+ $(EdkIIGlueLib_INCLUDES)\
+ $(iAMT_INCLUDES)\
+ $(IndustryStandard_INCLUDES)
+
+PpmAslUpdateLib_DEFINES=\
+ $(MY_DEFINES)\
+ /D __EDKII_GLUE_BASE_MEMORY_LIB__\
+ /D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__\
+
+PpmAslUpdateLib_LIBS=\
+ $(EdkIIGlueBaseMemoryLib_LIB)\
+ $(EdkIIGlueUefiBootServicesTableLib_LIB)\
+
+PpmAslUpdateLibBin :
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\PpmAslUpdateLib.mak all \
+ "MY_INCLUDES=$(PpmAslUpdateLib_INCLUDES)"\
+ "MY_DEFINES=$(PpmAslUpdateLib_DEFINES)"\
+ TYPE=LIBRARY\ \ No newline at end of file
diff --git a/ReferenceCode/Haswell/SampleCode/Library/AslUpdate/Dxe/PpmAslUpdateLib.sdl b/ReferenceCode/Haswell/SampleCode/Library/AslUpdate/Dxe/PpmAslUpdateLib.sdl
new file mode 100644
index 0000000..0a74ab2
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/AslUpdate/Dxe/PpmAslUpdateLib.sdl
@@ -0,0 +1,29 @@
+TOKEN
+ Name = PpmAslUpdateLib_SUPPORT
+ Value = 1
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+ Help = "Main switch to enable AslUpdateLib support in Project"
+End
+
+MODULE
+ Help = "Includes PpmAslUpdateLib.mak to Project"
+ File = "PpmAslUpdateLib.mak"
+End
+
+PATH
+ Name = "PpmAslUpdateLib_DIR"
+End
+
+ELINK
+ Name = "PpmAslUpdateLib_LIB"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\PpmAslUpdateLib.lib"
+ Parent = "PpmAslUpdateLib_LIB"
+ InvokeOrder = AfterParent
+End
diff --git a/ReferenceCode/Haswell/SampleCode/Library/BootGuardRevocationLib/Dxe/BootGuardRevocationLib.c b/ReferenceCode/Haswell/SampleCode/Library/BootGuardRevocationLib/Dxe/BootGuardRevocationLib.c
new file mode 100644
index 0000000..2a3ff51
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/BootGuardRevocationLib/Dxe/BootGuardRevocationLib.c
@@ -0,0 +1,34 @@
+/** @file
+ This file is SampleCode for Boot Guard revocation notification.
+
+@copyright
+ Copyright (c) 2012 - 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
+
+**/
+
+#include "BootGuardRevocationLib.h"
+
+/**
+ Provide a hook for OEM to deal with Boot Guard revocation flow.
+**/
+VOID
+EFIAPI
+BootGuardOemRevocationHook (
+ VOID
+ )
+{
+
+ return;
+}
diff --git a/ReferenceCode/Haswell/SampleCode/Library/BootGuardRevocationLib/Dxe/BootGuardRevocationLib.cif b/ReferenceCode/Haswell/SampleCode/Library/BootGuardRevocationLib/Dxe/BootGuardRevocationLib.cif
new file mode 100644
index 0000000..fdad18a
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/BootGuardRevocationLib/Dxe/BootGuardRevocationLib.cif
@@ -0,0 +1,11 @@
+<component>
+ name = "BootGuardRevocationLib"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\SampleCode\Library\BootGuardRevocationLib\Dxe"
+ RefName = "BootGuardRevocationLib"
+[files]
+"BootGuardRevocationLib.sdl"
+"BootGuardRevocationLib.mak"
+"BootGuardRevocationLib.c"
+"BootGuardRevocationLib.inf"
+<endComponent>
diff --git a/ReferenceCode/Haswell/SampleCode/Library/BootGuardRevocationLib/Dxe/BootGuardRevocationLib.inf b/ReferenceCode/Haswell/SampleCode/Library/BootGuardRevocationLib/Dxe/BootGuardRevocationLib.inf
new file mode 100644
index 0000000..295dcf6
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/BootGuardRevocationLib/Dxe/BootGuardRevocationLib.inf
@@ -0,0 +1,73 @@
+## @file
+# Provides services to display Boot Guard revocation notification.
+#
+#@copyright
+# Copyright (c) 2012 - 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
+#
+
+[defines]
+BASE_NAME = BootGuardRevocationLib
+COMPONENT_TYPE = LIBRARY
+
+[sources.common]
+ BootGuardRevocationLib.c
+
+[includes.common]
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+#
+# Typically the sample code referenced will be available in the code base already
+# So keep this include at the end to defer to the source base definition
+# and only use the sample code definition if source base does not include these files.
+#
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/SampleCode/Include
+
+#
+# Edk II Glue Library, some hearder are included by R9 header so have to include
+#
+
+ $(EFI_SOURCE)
+ $(EFI_SOURCE)/Framework
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+
+[libraries.common]
+ EdkIIGlueDxeReportStatusCodeLib
+ EdkIIGlueDxeDebugLibReportStatusCode
+ EdkIIGlueBaseMemoryLib
+ EdkIIGlueUefiBootServicesTableLib
+ EdkIIGlueUefiRuntimeServicesTableLib
+ EdkIIGlueUefiLib
+ EdkFrameworkProtocolLib
+
+[nmake.common]
+
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_DXE_REPORT_STATUS_CODE_LIB__ \
+ -D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ -D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ -D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_UEFI_LIB__ \ No newline at end of file
diff --git a/ReferenceCode/Haswell/SampleCode/Library/BootGuardRevocationLib/Dxe/BootGuardRevocationLib.mak b/ReferenceCode/Haswell/SampleCode/Library/BootGuardRevocationLib/Dxe/BootGuardRevocationLib.mak
new file mode 100644
index 0000000..2d3c433
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/BootGuardRevocationLib/Dxe/BootGuardRevocationLib.mak
@@ -0,0 +1,31 @@
+# MAK file for the ModulePart:AslUpdateLib
+all : BootGuardRevocationLib
+
+$(BUILD_DIR)\BootGuardRevocationLib.lib : BootGuardRevocationLib
+
+BootGuardRevocationLib : $(BUILD_DIR)\BootGuardRevocationLib.mak BootGuardRevocationLibBin
+
+$(BUILD_DIR)\BootGuardRevocationLib.mak : $(BootGuardRevocationLib_DIR)\$(@B).cif $(BootGuardRevocationLib_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(BootGuardRevocationLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+BootGuardRevocationLib_INCLUDES=\
+ $(PROJECT_CPU_INCLUDES)\
+ $(EdkIIGlueLib_INCLUDES)\
+ $(iAMT_INCLUDES)\
+ $(IndustryStandard_INCLUDES)
+
+BootGuardRevocationLib_DEFINES=\
+ $(MY_DEFINES)\
+ /D __EDKII_GLUE_BASE_MEMORY_LIB__\
+ /D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__\
+
+BootGuardRevocationLib_LIBS=\
+ $(EdkIIGlueBaseMemoryLib_LIB)\
+ $(EdkIIGlueUefiBootServicesTableLib_LIB)\
+
+BootGuardRevocationLibBin :
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\BootGuardRevocationLib.mak all \
+ "MY_INCLUDES=$(BootGuardRevocationLib_INCLUDES)"\
+ "MY_DEFINES=$(BootGuardRevocationLib_DEFINES)"\
+ TYPE=LIBRARY\ \ No newline at end of file
diff --git a/ReferenceCode/Haswell/SampleCode/Library/BootGuardRevocationLib/Dxe/BootGuardRevocationLib.sdl b/ReferenceCode/Haswell/SampleCode/Library/BootGuardRevocationLib/Dxe/BootGuardRevocationLib.sdl
new file mode 100644
index 0000000..b7405cf
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/BootGuardRevocationLib/Dxe/BootGuardRevocationLib.sdl
@@ -0,0 +1,29 @@
+TOKEN
+ Name = BootGuardRevocationLib_SUPPORT
+ Value = 1
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+ Help = "Main switch to enable BootGuardRevocationLib support in Project"
+End
+
+MODULE
+ Help = "Includes BootGuardRevocationLib.mak to Project"
+ File = "BootGuardRevocationLib.mak"
+End
+
+PATH
+ Name = "BootGuardRevocationLib_DIR"
+End
+
+ELINK
+ Name = "BootGuardRevocationLib_LIB"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\BootGuardRevocationLib.lib"
+ Parent = "BootGuardRevocationLib_LIB"
+ InvokeOrder = AfterParent
+End
diff --git a/ReferenceCode/Haswell/SampleCode/Library/BootGuardTpmEventLogLib/BootGuardTpmEventLogLib.c b/ReferenceCode/Haswell/SampleCode/Library/BootGuardTpmEventLogLib/BootGuardTpmEventLogLib.c
new file mode 100644
index 0000000..ffb8480
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/BootGuardTpmEventLogLib/BootGuardTpmEventLogLib.c
@@ -0,0 +1,838 @@
+/** @file
+ This file is SampleCode for Boot Guard TPM event log.
+
+@copyright
+ Copyright (c) 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
+**/
+
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueBase.h"
+#include "EdkIIGluePeim.h"
+#include "CpuAccess.h"
+#endif
+
+#include <EfiTpm.h>
+#include "BootGuardTpmEventLogLib.h"
+
+//
+// Data structure definition
+//
+#pragma pack (1)
+
+#define BASE_4GB 0x0000000100000000ULL
+//
+// FIT definition
+//
+#define FIT_TABLE_TYPE_HEADER 0x0
+#define FIT_TABLE_TYPE_MICROCODE 0x1
+#define FIT_TABLE_TYPE_STARTUP_ACM 0x2
+#define FIT_TABLE_TYPE_BIOS_MODULE 0x7
+#define FIT_TABLE_TYPE_KEY_MANIFEST 0xB
+#define FIT_TABLE_TYPE_BOOT_POLICY_MANIFEST 0xC
+
+typedef struct {
+ UINT64 Address;
+ UINT8 Size[3];
+ UINT8 Reserved;
+ UINT16 Version;
+ UINT8 Type : 7;
+ UINT8 Cv : 1;
+ UINT8 Chksum;
+} FIRMWARE_INTERFACE_TABLE_ENTRY;
+
+//
+// ACM definition
+//
+#define MMIO_ACM_STATUS (TXT_PUBLIC_BASE + R_CPU_BOOT_GUARD_ACM_STATUS)
+#define ACM_KEY_HASH_MMIO_ADDR_0 0xFED30400
+#define ACM_KEY_HASH_MMIO_ADDR_1 (ACM_KEY_HASH_MMIO_ADDR_0 + 8)
+#define ACM_KEY_HASH_MMIO_ADDR_2 (ACM_KEY_HASH_MMIO_ADDR_0 + 16)
+#define ACM_KEY_HASH_MMIO_ADDR_3 (ACM_KEY_HASH_MMIO_ADDR_0 + 24)
+#define ACM_PKCS_1_5_RSA_SIGNATURE_SIZE 256
+#define ACM_HEADER_FLAG_DEBUG_SIGNED BIT15
+#define ACM_NPW_SVN 0x2
+
+typedef struct {
+ UINT32 ModuleType;
+ UINT32 HeaderLen;
+ UINT32 HeaderVersion;
+ UINT16 ChipsetId;
+ UINT16 Flags;
+ UINT32 ModuleVendor;
+ UINT32 Date;
+ UINT32 Size;
+ UINT16 AcmSvn;
+ UINT16 Reserved1;
+ UINT32 CodeControl;
+ UINT32 ErrorEntryPoint;
+ UINT32 GdtLimit;
+ UINT32 GdtBasePtr;
+ UINT32 SegSel;
+ UINT32 EntryPoint;
+ UINT8 Reserved2[64];
+ UINT32 KeySize;
+ UINT32 ScratchSize;
+ UINT8 RsaPubKey[64 * 4];
+ UINT32 RsaPubExp;
+ UINT8 RsaSig[256];
+} ACM_FORMAT;
+
+//
+// Manifest definition
+//
+#define SHA256_DIGEST_SIZE 32
+
+typedef struct {
+ UINT16 HashAlg;
+ UINT16 Size;
+ UINT8 HashBuffer[SHA256_DIGEST_SIZE];
+} HASH_STRUCTURE;
+
+#define RSA_PUBLIC_KEY_STRUCT_KEY_SIZE_DEFAULT 2048
+#define RSA_PUBLIC_KEY_STRUCT_KEY_LEN_DEFAULT (RSA_PUBLIC_KEY_STRUCT_KEY_SIZE_DEFAULT/8)
+
+typedef struct {
+ UINT8 Version;
+ UINT16 KeySize;
+ UINT32 Exponent;
+ UINT8 Modulus[RSA_PUBLIC_KEY_STRUCT_KEY_LEN_DEFAULT];
+} RSA_PUBLIC_KEY_STRUCT;
+
+#define RSASSA_SIGNATURE_STRUCT_KEY_SIZE_DEFAULT 2048
+#define RSASSA_SIGNATURE_STRUCT_KEY_LEN_DEFAULT (RSASSA_SIGNATURE_STRUCT_KEY_SIZE_DEFAULT/8)
+typedef struct {
+ UINT8 Version;
+ UINT16 KeySize;
+ UINT16 HashAlg;
+ UINT8 Signature[RSASSA_SIGNATURE_STRUCT_KEY_LEN_DEFAULT];
+} RSASSA_SIGNATURE_STRUCT;
+
+typedef struct {
+ UINT8 Version;
+ UINT16 KeyAlg;
+ RSA_PUBLIC_KEY_STRUCT Key;
+ UINT16 SigScheme;
+ RSASSA_SIGNATURE_STRUCT Signature;
+} KEY_SIGNATURE_STRUCT;
+
+#define BOOT_POLICY_MANIFEST_HEADER_STRUCTURE_ID (*(UINT64 *)"__ACBP__")
+typedef struct {
+ UINT8 StructureId[8];
+ UINT8 StructVersion;
+ UINT8 HdrStructVersion;
+ UINT8 PMBPMVersion;
+ UINT8 BPSVN;
+ UINT8 ACMSVN;
+ UINT8 Reserved;
+ UINT16 NEMDataStack;
+} BOOT_POLICY_MANIFEST_HEADER;
+
+#define IBB_SEGMENT_FLAG_IBB 0x0
+#define IBB_SEGMENT_FLAG_NON_IBB 0x1
+typedef struct {
+ UINT8 Reserved[2];
+ UINT16 Flags;
+ UINT32 Base;
+ UINT32 Size;
+} IBB_SEGMENT_ELEMENT;
+
+#define BOOT_POLICY_MANIFEST_IBB_ELEMENT_STRUCTURE_ID (*(UINT64 *)"__IBBS__")
+#define IBB_FLAG_AUTHORITY_MEASURE 0x4
+
+typedef struct {
+ UINT8 StructureId[8];
+ UINT8 StructVersion;
+ UINT8 Reserved1[2];
+ UINT8 PbetValue;
+ UINT32 Flags;
+ UINT64 IbbMchBar;
+ UINT64 VtdBar;
+ UINT32 PmrlBase;
+ UINT32 PmrlLimit;
+ UINT64 Reserved2[2];
+ HASH_STRUCTURE PostIbbHash;
+ UINT32 EntryPoint;
+ HASH_STRUCTURE Digest;
+ UINT8 SegmentCount;
+ IBB_SEGMENT_ELEMENT IbbSegment[1];
+} IBB_ELEMENT;
+
+#define BOOT_POLICY_MANIFEST_PLATFORM_MANUFACTURER_ELEMENT_STRUCTURE_ID (*(UINT64 *)"__PMDA__")
+typedef struct {
+ UINT8 StructureId[8];
+ UINT8 StructVersion;
+ UINT16 PmDataSize;
+} PLATFORM_MANUFACTURER_ELEMENT;
+
+#define BOOT_POLICY_MANIFEST_SIGNATURE_ELEMENT_STRUCTURE_ID (*(UINT64 *)"__PMSG__")
+typedef struct {
+ UINT8 StructureId[8];
+ UINT8 StructVersion;
+ KEY_SIGNATURE_STRUCT KeySignature;
+} BOOT_POLICY_MANIFEST_SIGNATURE_ELEMENT;
+
+#define KEY_MANIFEST_STRUCTURE_ID (*(UINT64 *)"__KEYM__")
+typedef struct {
+ UINT8 StructureId[8];
+ UINT8 StructVersion;
+ UINT8 KeyManifestVersion;
+ UINT8 KmSvn;
+ UINT8 KeyManifestId;
+ HASH_STRUCTURE BpKey;
+ KEY_SIGNATURE_STRUCT KeyManifestSignature;
+} KEY_MANIFEST_STRAUCTURE;
+
+//
+// DetailPCR data
+//
+typedef struct {
+ UINT8 BpRstrLow;
+ UINT8 BpTypeLow;
+ UINT16 AcmSvn;
+ UINT8 AcmRsaSignature[ACM_PKCS_1_5_RSA_SIGNATURE_SIZE];
+ UINT8 KmRsaSignature[RSASSA_SIGNATURE_STRUCT_KEY_LEN_DEFAULT];
+ UINT8 BpmRsaSignature[RSASSA_SIGNATURE_STRUCT_KEY_LEN_DEFAULT];
+ UINT8 IbbHash[SHA256_DIGEST_SIZE];
+} DETAIL_PCR_DATA;
+
+//
+// AuthorityPCR data
+//
+typedef struct {
+ UINT8 BpRstrLow;
+ UINT8 BpTypeLow;
+ UINT16 AcmSvn;
+ UINT8 AcmKeyHash[SHA256_DIGEST_SIZE];
+ UINT8 BpKeyHash[SHA256_DIGEST_SIZE];
+ UINT8 BpmKeyHashFromKm[SHA256_DIGEST_SIZE];
+ UINT8 VerifiedBoot;
+} AUTHORITY_PCR_DATA;
+
+//
+// Boot Policy Restrictions definition
+//
+typedef union {
+ struct {
+ UINT8 Facb : 1;
+ UINT8 Dcd : 1;
+ UINT8 Dbi : 1;
+ UINT8 Pbe : 1;
+ UINT8 Bbp : 1;
+ UINT8 Reserved : 2;
+ UINT8 BpInvd : 1;
+ } Bits;
+ UINT8 Data;
+} BP_RSTR_LOW;
+
+//
+// Boot Policy Type definition
+//
+typedef union {
+ struct {
+ UINT8 MeasuredBoot : 1;
+ UINT8 VerifiedBoot : 1;
+ UINT8 Hap : 1;
+ UINT8 Reserved : 5;
+ } Bits;
+ UINT8 Data;
+} BP_TYPE_LOW;
+
+#pragma pack ()
+
+//
+// OEM_IMPLEMENTATION_BEGIN
+//
+// SHA calculation and TPM functions are OEM Core/Platform code depended,
+// OEM can customize these empty functions for their specific.
+//
+// For the detail of SHA algorithm, please refer to FIPS PUB 180-2.
+// For TPM event log, please refer to TCG EFI Protocol Specification.
+//
+
+//
+// Null-defined macro for passing EDK build
+//
+#define SHA_INIT
+#define SHA_UPDATE
+#define SHA_FINAL
+
+/**
+ Calculate SHA-1 Hash
+
+ @param[in] Data Data to be hashed.
+ @param[in] Size Size of data.
+ @param[out] Digest SHA-1 digest value.
+**/
+VOID
+CreateSha1Hash (
+ IN UINT8 *Data,
+ IN UINTN Size,
+ OUT UINT8 *Digest
+ )
+{
+ VOID *Context;
+
+ SHA_INIT (Context);
+ SHA_UPDATE (Context, Data, Size);
+ SHA_FINAL (Context, Digest);
+
+ return;
+}
+
+/**
+ Calculate SHA256 Hash
+
+ @param[in] Data Data to be hashed.
+ @param[in] Size Size of data.
+ @param[out] Digest SHA256 digest value.
+**/
+VOID
+CreateSha256Hash (
+ IN UINT8 *Data,
+ IN UINTN Size,
+ OUT UINT8 *Digest
+ )
+{
+ VOID *Context;
+
+ SHA_INIT (Context);
+ SHA_UPDATE (Context, Data, Size);
+ SHA_FINAL (Context, Digest);
+
+ return;
+}
+
+/**
+ Add a new entry to the Event Log.
+
+ @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
+ @param[in] NewEventData Pointer to the new event data.
+
+ @retval EFI_SUCCESS The new event log entry was added.
+ @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
+**/
+EFI_STATUS
+LogEvent (
+ IN TCG_PCR_EVENT_HDR *NewEventHdr,
+ IN UINT8 *NewEventData
+ )
+{
+
+ return EFI_SUCCESS;
+}
+//
+// OEM_IMPLEMENTATION_END
+//
+
+/**
+ Find FIT Entry address data by type
+
+ @param[in] Type FIT Entry type
+
+ @return FIT entry address
+**/
+VOID *
+FindFitEntryData (
+ IN UINT8 Type
+ )
+{
+ FIRMWARE_INTERFACE_TABLE_ENTRY *FitEntry;
+ UINT32 EntryNum;
+ UINT64 FitTableOffset;
+ UINT32 Index;
+
+ FitTableOffset = *(UINT64 *)(UINTN)(BASE_4GB - 0x40);
+ FitEntry = (FIRMWARE_INTERFACE_TABLE_ENTRY *)(UINTN)FitTableOffset;
+ if (FitEntry[0].Address != *(UINT64 *)"_FIT_ ") {
+ return NULL;
+ }
+ if (FitEntry[0].Type != FIT_TABLE_TYPE_HEADER) {
+ return NULL;
+ }
+ EntryNum = *(UINT32 *)(&FitEntry[0].Size[0]) & 0xFFFFFF;
+ for (Index = 0; Index < EntryNum; Index++) {
+ if (FitEntry[Index].Type == Type) {
+ return (VOID *)(UINTN)FitEntry[Index].Address;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ Find the address of ACM.
+
+ @return A pointer to ACM.
+**/
+VOID *
+FindAcm (
+ VOID
+ )
+{
+ return FindFitEntryData (FIT_TABLE_TYPE_STARTUP_ACM);
+}
+
+/**
+ Find the address of Boot Policy Manifest.
+
+ @return A pointer to Key Manifest data structure.
+**/
+VOID *
+FindBpm (
+ VOID
+ )
+{
+ return FindFitEntryData (FIT_TABLE_TYPE_BOOT_POLICY_MANIFEST);
+}
+
+/**
+ Find the address of Key Manifest.
+
+ @return A pointer to Key Manifest data structure.
+**/
+VOID *
+FindKm (
+ VOID
+ )
+{
+ return FindFitEntryData (FIT_TABLE_TYPE_KEY_MANIFEST);
+}
+
+/**
+ Find BPM element by structureID
+
+ @param[in] Bpm A pointer to BPM data structure.
+ @param[in] StructureId BPM element StructureID
+
+ @return A pointer to BPM element data structure.
+**/
+VOID *
+FindBpmElement (
+ IN BOOT_POLICY_MANIFEST_HEADER *Bpm,
+ IN UINT64 StructureId
+ )
+{
+ BOOT_POLICY_MANIFEST_HEADER *BpmHeader;
+ IBB_ELEMENT *IbbElement;
+ PLATFORM_MANUFACTURER_ELEMENT *PmElement;
+ BOOT_POLICY_MANIFEST_SIGNATURE_ELEMENT *BpmSignatureElement;
+ UINT8 *Buffer;
+
+ Buffer = (UINT8 *)Bpm;
+
+ BpmHeader = (BOOT_POLICY_MANIFEST_HEADER *)Buffer;
+ if (*(UINT64 *)BpmHeader->StructureId != BOOT_POLICY_MANIFEST_HEADER_STRUCTURE_ID) {
+ return NULL;
+ }
+ if (StructureId == BOOT_POLICY_MANIFEST_HEADER_STRUCTURE_ID) {
+ return Buffer;
+ }
+ Buffer += sizeof(BOOT_POLICY_MANIFEST_HEADER);
+
+ IbbElement = (IBB_ELEMENT *)Buffer;
+ if (*(UINT64 *)IbbElement->StructureId != BOOT_POLICY_MANIFEST_IBB_ELEMENT_STRUCTURE_ID) {
+ return NULL;
+ }
+ if (StructureId == BOOT_POLICY_MANIFEST_IBB_ELEMENT_STRUCTURE_ID) {
+ return Buffer;
+ }
+ Buffer += sizeof(IBB_ELEMENT) + sizeof(IBB_SEGMENT_ELEMENT) * (IbbElement->SegmentCount - 1);
+
+ PmElement = (PLATFORM_MANUFACTURER_ELEMENT *)Buffer;
+ while (*(UINT64 *)PmElement->StructureId == BOOT_POLICY_MANIFEST_PLATFORM_MANUFACTURER_ELEMENT_STRUCTURE_ID) {
+ if (StructureId == BOOT_POLICY_MANIFEST_PLATFORM_MANUFACTURER_ELEMENT_STRUCTURE_ID) {
+ return Buffer;
+ }
+ Buffer += sizeof(PLATFORM_MANUFACTURER_ELEMENT) + PmElement->PmDataSize;
+ PmElement = (PLATFORM_MANUFACTURER_ELEMENT *)Buffer;
+ }
+
+ BpmSignatureElement = (BOOT_POLICY_MANIFEST_SIGNATURE_ELEMENT *)Buffer;
+ if (*(UINT64 *)BpmSignatureElement->StructureId != BOOT_POLICY_MANIFEST_SIGNATURE_ELEMENT_STRUCTURE_ID) {
+ return NULL;
+ }
+ if (StructureId == BOOT_POLICY_MANIFEST_SIGNATURE_ELEMENT_STRUCTURE_ID) {
+ return Buffer;
+ }
+ return NULL;
+}
+
+/**
+ Find BPM IBB element
+
+ @param[in] Bpm A pointer to BPM data structure.
+
+ @return A pointer to BPM IBB element data structure.
+**/
+VOID *
+FindBpmIbb (
+ IN BOOT_POLICY_MANIFEST_HEADER *Bpm
+ )
+{
+ return FindBpmElement (Bpm, BOOT_POLICY_MANIFEST_IBB_ELEMENT_STRUCTURE_ID);
+}
+
+/**
+ Find BPM Signature element
+
+ @param[in] Bpm BPM address
+
+ @return BPM Signature element
+**/
+VOID *
+FindBpmSignature (
+ IN BOOT_POLICY_MANIFEST_HEADER *Bpm
+ )
+{
+ return FindBpmElement (Bpm, BOOT_POLICY_MANIFEST_SIGNATURE_ELEMENT_STRUCTURE_ID);
+}
+
+/**
+ Check if ACM is a NPW ACM.
+
+ @retval TRUE It is a NPW ACM
+ @retval FALSE It is NOT a NPW ACM
+**/
+BOOLEAN
+IsNpwAcm (
+ VOID
+ )
+{
+ ACM_FORMAT *Acm;
+
+ Acm = FindAcm ();
+ ASSERT (Acm != NULL);
+ if (Acm == NULL) {
+ return FALSE;
+ }
+
+ if (((Acm->Flags & ACM_HEADER_FLAG_DEBUG_SIGNED) == 0) && (Acm->AcmSvn < ACM_NPW_SVN)) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ Check if Boot Guard verifies the IBB.
+
+ @retval TRUE It is VerifiedBoot
+ @retval FALSE It is NOT VerifiedBoot
+**/
+BOOLEAN
+IsVerifiedBoot (
+ VOID
+ )
+{
+ if ((AsmReadMsr64 (MSR_BOOT_GUARD_SACM_INFO) & B_VERIFIED) != 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ Check if Boot Guard measures IBB into TPM's PCRs.
+
+ @retval TRUE It is MeasuredBoot
+ @retval FALSE It is NOT MeasuredBoot
+**/
+BOOLEAN
+IsMeasuredBoot (
+ VOID
+ )
+{
+ if ((AsmReadMsr64 (MSR_BOOT_GUARD_SACM_INFO) & B_MEASURED) != 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ Get the lower 8 bits of Boot Policy Restrictions
+
+ @return The lower 8 bits of BP.RSTR
+**/
+UINT8
+GetBpRstrLow (
+ VOID
+ )
+{
+ BP_RSTR_LOW BpRstr;
+ UINT32 AcmStatus;
+ UINT64 SacmInfo;
+
+ AcmStatus = MmioRead32 (MMIO_ACM_STATUS);
+ SacmInfo = AsmReadMsr64 (MSR_BOOT_GUARD_SACM_INFO);
+
+ BpRstr.Bits.Facb = (UINT8)((SacmInfo & BIT4) >> 4);
+ BpRstr.Bits.Dcd = (UINT8)((AcmStatus & BIT21) >> 21);
+ BpRstr.Bits.Dbi = (UINT8)((AcmStatus & BIT22) >> 22);
+ BpRstr.Bits.Pbe = (UINT8)((AcmStatus & BIT23) >> 23);
+ BpRstr.Bits.Bbp = (UINT8)((AcmStatus & BIT24) >> 24);
+ BpRstr.Bits.Reserved = 0;
+ BpRstr.Bits.BpInvd = 0;
+
+ return BpRstr.Data;
+}
+
+/**
+ Get the lower 8 bits of Boot Policy Type
+
+ @return The lower 8 bits of BP.TYPE
+**/
+UINT8
+GetBpTypeLow (
+ VOID
+ )
+{
+ BP_TYPE_LOW BpType;
+ UINT32 AcmStatus;
+ UINT64 SacmInfo;
+
+ AcmStatus = MmioRead32 (MMIO_ACM_STATUS);
+ SacmInfo = AsmReadMsr64 (MSR_BOOT_GUARD_SACM_INFO);
+
+ BpType.Bits.MeasuredBoot = (UINT8)((SacmInfo & BIT5) >> 5);
+ BpType.Bits.VerifiedBoot = (UINT8)((SacmInfo & BIT6) >> 6);
+ BpType.Bits.Hap = (UINT8)((AcmStatus & BIT20) >> 20);
+ BpType.Bits.Reserved = 0;
+
+ return BpType.Data;
+}
+
+/**
+ Calculate IBB Hash
+
+ @param[in] BpmIbb A pointer to BPM IBB element data structure.
+ @param[out] Digest IBB digest value.
+**/
+VOID
+CreateIbbHash (
+ IN IBB_ELEMENT *BpmIbb,
+ OUT UINT8 *Digest
+ )
+{
+ VOID *Context;
+ UINTN Index;
+
+ SHA_INIT (Context);
+
+ for (Index = 0; Index < BpmIbb->SegmentCount; Index++) {
+ if (BpmIbb->IbbSegment[Index].Flags == IBB_SEGMENT_FLAG_IBB) {
+ SHA_UPDATE (Context, (VOID *)(UINTN)BpmIbb->IbbSegment[Index].Base, BpmIbb->IbbSegment[Index].Size);
+ }
+ }
+
+ SHA_FINAL (Context, Digest);
+
+ return;
+}
+
+/**
+ Calculate DetailPCR extend value
+
+ @param[out] Digest DetailPCR digest
+**/
+VOID
+CaculateDetailPCRExtendValue (
+ OUT TCG_DIGEST *Digest
+ )
+{
+ ACM_FORMAT *Acm;
+ KEY_MANIFEST_STRAUCTURE *Km;
+ BOOT_POLICY_MANIFEST_HEADER *Bpm;
+ IBB_ELEMENT *BpmIbb;
+ BOOT_POLICY_MANIFEST_SIGNATURE_ELEMENT *BpmSignature;
+ DETAIL_PCR_DATA DetailPcrData;
+
+ Acm = FindAcm ();
+ ASSERT (Acm != NULL);
+
+ Km = FindKm ();
+ ASSERT (Km != NULL);
+
+ Bpm = FindBpm ();
+ ASSERT (Bpm != NULL);
+
+ BpmIbb = FindBpmIbb (Bpm);
+ ASSERT (BpmIbb != NULL);
+
+ BpmSignature = FindBpmSignature (Bpm);
+ ASSERT (BpmSignature != NULL);
+
+ DetailPcrData.BpRstrLow = GetBpRstrLow ();
+ DetailPcrData.BpTypeLow = GetBpTypeLow ();
+ DetailPcrData.AcmSvn = Acm->AcmSvn;
+ CopyMem (&DetailPcrData.AcmRsaSignature, &Acm->RsaSig, sizeof(DetailPcrData.AcmRsaSignature));
+ CopyMem (&DetailPcrData.KmRsaSignature, &Km->KeyManifestSignature.Signature.Signature, sizeof(DetailPcrData.KmRsaSignature));
+ CopyMem (&DetailPcrData.BpmRsaSignature, &BpmSignature->KeySignature.Signature.Signature, sizeof(DetailPcrData.BpmRsaSignature));
+ if (IsVerifiedBoot ()) {
+ CopyMem (&DetailPcrData.IbbHash, &BpmIbb->Digest.HashBuffer, sizeof(DetailPcrData.IbbHash));
+ } else {
+ //
+ // Calculate IBB hash because it is NOT verified boot, the Digest from IBB can not be trust.
+ //
+ CreateIbbHash (BpmIbb, (UINT8 *)&DetailPcrData.IbbHash);
+ }
+
+ CreateSha1Hash ((UINT8 *)&DetailPcrData, sizeof(DetailPcrData), (UINT8 *)Digest);
+}
+
+/**
+ Calculate AuthorityPCR extend value
+
+ @param[out] Digest AuthorityPCR digest
+**/
+VOID
+CaculateAuthorityPCRExtendValue (
+ OUT TCG_DIGEST *Digest
+ )
+{
+ ACM_FORMAT *Acm;
+ KEY_MANIFEST_STRAUCTURE *Km;
+ AUTHORITY_PCR_DATA AuthorityPcrData;
+
+ Acm = FindAcm ();
+ ASSERT (Acm != NULL);
+
+ Km = FindKm ();
+ ASSERT (Km != NULL);
+
+ AuthorityPcrData.BpRstrLow = GetBpRstrLow ();
+ AuthorityPcrData.BpTypeLow = GetBpTypeLow ();
+ AuthorityPcrData.AcmSvn = Acm->AcmSvn;
+
+ //
+ // Get ACM Key hash
+ //
+ *(UINT64 *)&AuthorityPcrData.AcmKeyHash[0] = MmioRead64 (ACM_KEY_HASH_MMIO_ADDR_0);
+ *(UINT64 *)&AuthorityPcrData.AcmKeyHash[8] = MmioRead64 (ACM_KEY_HASH_MMIO_ADDR_1);
+ *(UINT64 *)&AuthorityPcrData.AcmKeyHash[16] = MmioRead64 (ACM_KEY_HASH_MMIO_ADDR_2);
+ *(UINT64 *)&AuthorityPcrData.AcmKeyHash[24] = MmioRead64 (ACM_KEY_HASH_MMIO_ADDR_3);
+
+ //
+ // Calculate BP Key hash
+ //
+ CreateSha256Hash ((UINT8 *)&Km->KeyManifestSignature.Key.Modulus, sizeof(Km->KeyManifestSignature.Key.Modulus), (UINT8 *)&AuthorityPcrData.BpKeyHash);
+
+ CopyMem (&AuthorityPcrData.BpmKeyHashFromKm, &Km->BpKey.HashBuffer, sizeof(AuthorityPcrData.BpmKeyHashFromKm));
+ if (IsVerifiedBoot ()) {
+ AuthorityPcrData.VerifiedBoot = 0;
+ } else {
+ AuthorityPcrData.VerifiedBoot = 1;
+ }
+
+ CreateSha1Hash ((UINT8 *)&AuthorityPcrData, sizeof(AuthorityPcrData), (UINT8 *)Digest);
+}
+
+/**
+ Check if we need AuthorityPCR measurement
+
+ @retval TRUE Need AuthorityPCR measurement
+ @retval FALSE Do NOT need AuthorityPCR measurement
+**/
+BOOLEAN
+NeedAuthorityMeasure (
+ VOID
+ )
+{
+ BOOT_POLICY_MANIFEST_HEADER *Bpm;
+ IBB_ELEMENT *BpmIbb;
+
+ Bpm = FindBpm ();
+ ASSERT (Bpm != NULL);
+
+ BpmIbb = FindBpmIbb (Bpm);
+ ASSERT (BpmIbb != NULL);
+
+ if ((BpmIbb->Flags & IBB_FLAG_AUTHORITY_MEASURE) != 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ Create DetailPCR event log
+
+ @param[in] TpmType TPM type
+**/
+VOID
+CreateDetailPcrEvent (
+ IN TPM_TYPE TpmType
+ )
+{
+ TCG_PCR_EVENT_HDR NewEventHdr;
+
+ NewEventHdr.PCRIndex = 0;
+ NewEventHdr.EventType = EV_S_CRTM_CONTENTS;
+ CaculateDetailPCRExtendValue (&NewEventHdr.Digest);
+
+ if (IsNpwAcm()) {
+ NewEventHdr.EventSize = sizeof ("Boot Guard Debug Measured S-CRTM");
+ LogEvent (&NewEventHdr, "Boot Guard Debug Measured S-CRTM");
+ } else {
+ NewEventHdr.EventSize = sizeof ("Boot Guard Measured S-CRTM");
+ LogEvent (&NewEventHdr, "Boot Guard Measured S-CRTM");
+ }
+}
+
+/**
+ Create AuthorityPCR event log
+
+ @param[in] TpmType TPM type
+**/
+VOID
+CreateAuthorityPcrEvent (
+ IN TPM_TYPE TpmType
+ )
+{
+ TCG_PCR_EVENT_HDR NewEventHdr;
+
+ if (NeedAuthorityMeasure() && IsVerifiedBoot()) {
+ if (TpmType == dTpm12) {
+ NewEventHdr.PCRIndex = 6;
+ } else {
+ NewEventHdr.PCRIndex = 7;
+ }
+ NewEventHdr.EventType = EV_EFI_VARIABLE_DRIVER_CONFIG;
+ CaculateAuthorityPCRExtendValue (&NewEventHdr.Digest);
+
+ if (IsNpwAcm()) {
+ NewEventHdr.EventSize = sizeof (L"Boot Guard Debug Measured S-CRTM");
+ LogEvent (&NewEventHdr, (UINT8 *)L"Boot Guard Debug Measured S-CRTM");
+ } else {
+ NewEventHdr.EventSize = sizeof (L"Boot Guard Measured S-CRTM");
+ LogEvent (&NewEventHdr, (UINT8 *)L"Boot Guard Measured S-CRTM");
+ }
+ }
+}
+
+/**
+ Create Boot Guard TPM event log
+
+ @param[in] TpmType Which type of TPM is available on system.
+**/
+VOID
+CreateTpmEventLog (
+ IN TPM_TYPE TpmType
+ )
+{
+ if (IsMeasuredBoot()) {
+ CreateDetailPcrEvent (TpmType);
+ CreateAuthorityPcrEvent (TpmType);
+ }
+}
diff --git a/ReferenceCode/Haswell/SampleCode/Library/BootGuardTpmEventLogLib/BootGuardTpmEventLogLib.cif b/ReferenceCode/Haswell/SampleCode/Library/BootGuardTpmEventLogLib/BootGuardTpmEventLogLib.cif
new file mode 100644
index 0000000..06d608a
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/BootGuardTpmEventLogLib/BootGuardTpmEventLogLib.cif
@@ -0,0 +1,11 @@
+<component>
+ name = "BootGuardTpmEventLogLib"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\SampleCode\Library\BootGuardTpmEventLogLib"
+ RefName = "BootGuardTpmEventLogLib"
+[files]
+"BootGuardTpmEventLogLib.sdl"
+"BootGuardTpmEventLogLib.mak"
+"BootGuardTpmEventLogLib.c"
+"BootGuardTpmEventLogLib.h"
+<endComponent>
diff --git a/ReferenceCode/Haswell/SampleCode/Library/BootGuardTpmEventLogLib/BootGuardTpmEventLogLib.h b/ReferenceCode/Haswell/SampleCode/Library/BootGuardTpmEventLogLib/BootGuardTpmEventLogLib.h
new file mode 100644
index 0000000..ca91990
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/BootGuardTpmEventLogLib/BootGuardTpmEventLogLib.h
@@ -0,0 +1,33 @@
+/** @file
+ Header file for Boot Guard TPM event log.
+
+@copyright
+ Copyright (c) 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
+**/
+#ifndef _BOOT_GUARD_TPM_EVENT_LOG_LIB_H_
+#define _BOOT_GUARD_TPM_EVENT_LOG_LIB_H_
+
+#include EFI_PPI_DEFINITION (CpuPlatformPolicy)
+
+/**
+ Create Boot Guard TPM event log
+
+ @param[in] TpmType - Which type of TPM is available on system.
+**/
+VOID
+CreateTpmEventLog (
+ IN TPM_TYPE TpmType
+ );
+
+#endif
diff --git a/ReferenceCode/Haswell/SampleCode/Library/BootGuardTpmEventLogLib/BootGuardTpmEventLogLib.mak b/ReferenceCode/Haswell/SampleCode/Library/BootGuardTpmEventLogLib/BootGuardTpmEventLogLib.mak
new file mode 100644
index 0000000..47a3d87
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/BootGuardTpmEventLogLib/BootGuardTpmEventLogLib.mak
@@ -0,0 +1,31 @@
+# MAK file for the ModulePart:AslUpdateLib
+all : BootGuardTpmEventLogLib
+
+$(BUILD_DIR)\BootGuardTpmEventLogLib.lib : BootGuardTpmEventLogLib
+
+BootGuardTpmEventLogLib : $(BUILD_DIR)\BootGuardTpmEventLogLib.mak BootGuardTpmEventLogLibBin
+
+$(BUILD_DIR)\BootGuardTpmEventLogLib.mak : $(BootGuardTpmEventLogLib_DIR)\$(@B).cif $(BootGuardTpmEventLogLib_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(BootGuardTpmEventLogLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+BootGuardTpmEventLogLib_INCLUDES=\
+ $(PROJECT_CPU_INCLUDES)\
+ $(EdkIIGlueLib_INCLUDES)\
+ $(iAMT_INCLUDES)\
+ $(IndustryStandard_INCLUDES)
+
+BootGuardTpmEventLogLib_DEFINES=\
+ $(MY_DEFINES)\
+ /D __EDKII_GLUE_BASE_MEMORY_LIB__\
+ /D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__\
+
+BootGuardTpmEventLogLib_LIBS=\
+ $(EdkIIGlueBaseMemoryLib_LIB)\
+ $(EdkIIGlueUefiBootServicesTableLib_LIB)\
+
+BootGuardTpmEventLogLibBin :
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\BootGuardTpmEventLogLib.mak all \
+ "MY_INCLUDES=$(BootGuardTpmEventLogLib_INCLUDES)"\
+ "MY_DEFINES=$(BootGuardTpmEventLogLib_DEFINES)"\
+ TYPE=LIBRARY\ \ No newline at end of file
diff --git a/ReferenceCode/Haswell/SampleCode/Library/BootGuardTpmEventLogLib/BootGuardTpmEventLogLib.sdl b/ReferenceCode/Haswell/SampleCode/Library/BootGuardTpmEventLogLib/BootGuardTpmEventLogLib.sdl
new file mode 100644
index 0000000..37c7417
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/BootGuardTpmEventLogLib/BootGuardTpmEventLogLib.sdl
@@ -0,0 +1,29 @@
+TOKEN
+ Name = BootGuardTpmEventLogLib_SUPPORT
+ Value = 1
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+ Help = "Main switch to enable BootGuardTpmEventLogLib support in Project"
+End
+
+MODULE
+ Help = "Includes BootGuardTpmEventLogLib.mak to Project"
+ File = "BootGuardTpmEventLogLib.mak"
+End
+
+PATH
+ Name = "BootGuardTpmEventLogLib_DIR"
+End
+
+ELINK
+ Name = "BootGuardTpmEventLogLib_LIB"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\BootGuardTpmEventLogLib.lib"
+ Parent = "BootGuardTpmEventLogLib_LIB"
+ InvokeOrder = AfterParent
+End
diff --git a/ReferenceCode/Haswell/SampleCode/Library/DTSHookLib/Smm/DTSHookLib.c b/ReferenceCode/Haswell/SampleCode/Library/DTSHookLib/Smm/DTSHookLib.c
new file mode 100644
index 0000000..05878cd
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/DTSHookLib/Smm/DTSHookLib.c
@@ -0,0 +1,71 @@
+/** @file
+ Digital Thermal Sensor (DTS) SMM Library.
+ This SMM Library configures and supports the DigitalThermalSensor features
+ for the platform.
+
+@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 "DTSHookLib.h"
+
+/**
+ Prepare data and protocol for Dts Hooe Lib
+
+ @retval EFI_SUCCESS - Initialize complete
+**/
+EFI_STATUS
+InitializeDtsHookLib (
+ VOID
+ )
+{
+ ///
+ /// Nothing to do on CRB.
+ ///
+ return EFI_SUCCESS;
+}
+
+/**
+ Platform may need to register some data to private data structure before generate
+ software SMI or SCI.
+**/
+VOID
+PlatformHookBeforeGenerateSCI (
+ VOID
+ )
+{
+ ///
+ /// Nothing to do on CRB.
+ ///
+}
+
+/**
+ When system temperature out of specification, do platform specific programming to prevent
+ system damage.
+**/
+VOID
+PlatformEventOutOfSpec (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ ///
+ /// Handle critical event by shutting down via EC
+ ///
+ Status = InitializeKscLib ();
+ if (Status == EFI_SUCCESS) {
+ SendKscCommand (KSC_C_SYSTEM_POWER_OFF);
+ }
+}
diff --git a/ReferenceCode/Haswell/SampleCode/Library/DTSHookLib/Smm/DTSHookLib.cif b/ReferenceCode/Haswell/SampleCode/Library/DTSHookLib/Smm/DTSHookLib.cif
new file mode 100644
index 0000000..6eddca3
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/DTSHookLib/Smm/DTSHookLib.cif
@@ -0,0 +1,12 @@
+<component>
+ name = "DTSHookLib"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\SampleCode\Library\DTSHookLib\Smm\"
+ RefName = "DTSHookLib"
+[files]
+"DTSHookLib.sdl"
+"DTSHookLib.mak"
+"DTSHookLib.inf"
+"DTSHookLib.c"
+"DTSHookLib.h"
+<endComponent>
diff --git a/ReferenceCode/Haswell/SampleCode/Library/DTSHookLib/Smm/DTSHookLib.h b/ReferenceCode/Haswell/SampleCode/Library/DTSHookLib/Smm/DTSHookLib.h
new file mode 100644
index 0000000..7dfaa9b
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/DTSHookLib/Smm/DTSHookLib.h
@@ -0,0 +1,27 @@
+/** @file
+ Defines and prototypes for the DigitalThermalSensor SMM driver
+
+@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
+**/
+#ifndef _DTS_LIB_H_
+#define _DTS_LIB_H_
+///
+/// Include files
+///
+#include "Tiano.h"
+#include "KscLib.h"
+
+#endif
diff --git a/ReferenceCode/Haswell/SampleCode/Library/DTSHookLib/Smm/DTSHookLib.inf b/ReferenceCode/Haswell/SampleCode/Library/DTSHookLib/Smm/DTSHookLib.inf
new file mode 100644
index 0000000..f4011cf
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/DTSHookLib/Smm/DTSHookLib.inf
@@ -0,0 +1,49 @@
+## @file
+# Component description file.
+#
+#@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
+#
+
+
+[defines]
+BASE_NAME = DTSHookLib
+COMPONENT_TYPE = LIBRARY
+
+[sources.common]
+ DTSHookLib.c
+ DTSHookLib.h
+
+[includes.common]
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EFI_SOURCE)/Framework
+ .
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EFI_SOURCE)
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+ $(EDK_SOURCE)/Foundation
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/SampleCode/Include
+
+[libraries.common]
+ EdkFrameworkProtocolLib
+
+[nmake.common]
+ C_STD_INCLUDE=
diff --git a/ReferenceCode/Haswell/SampleCode/Library/DTSHookLib/Smm/DTSHookLib.mak b/ReferenceCode/Haswell/SampleCode/Library/DTSHookLib/Smm/DTSHookLib.mak
new file mode 100644
index 0000000..9b10b29
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/DTSHookLib/Smm/DTSHookLib.mak
@@ -0,0 +1,15 @@
+# MAK file for the ModulePart:CpuPlatformLib
+
+$(DTSHookLib_LIB) : DTSHookLib
+
+DTSHookLib : $(BUILD_DIR)\DTSHookLib.mak DTSHookLibBin
+
+$(BUILD_DIR)\DTSHookLib.mak : $(DTSHookLib_DIR)\$(@B).cif $(DTSHookLib_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(DTSHookLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+DTSHookLibBin :
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ BUILD_DIR=$(BUILD_DIR) \
+ /f $(BUILD_DIR)\DTSHookLib.mak all\
+ "MY_INCLUDES=$(EDK_INCLUDES) $(EdkIIGlueLib_INCLUDES) $(PROJECT_CPU_INCLUDES)" \
+ TYPE=LIBRARY "PARAMETERS=LIBRARY_NAME=$$(DTSHookLib_LIB)" \ No newline at end of file
diff --git a/ReferenceCode/Haswell/SampleCode/Library/DTSHookLib/Smm/DTSHookLib.sdl b/ReferenceCode/Haswell/SampleCode/Library/DTSHookLib/Smm/DTSHookLib.sdl
new file mode 100644
index 0000000..e49c48f
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/DTSHookLib/Smm/DTSHookLib.sdl
@@ -0,0 +1,25 @@
+TOKEN
+ Name = DTSHookLib_SUPPORT
+ Value = 1
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+ Help = "Main switch to enable DTSHookLib support in Project"
+End
+
+TOKEN
+ Name = "DTSHookLib_LIB"
+ Value = "$$(LIB_BUILD_DIR)\DTSHookLib.lib"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+MODULE
+ Help = "Includes DTSHookLib.mak to Project"
+ File = "DTSHookLib.mak"
+End
+
+PATH
+ Name = "DTSHookLib_DIR"
+End \ No newline at end of file
diff --git a/ReferenceCode/Haswell/SampleCode/Library/Ksc/Smm/SmmKscLib.c b/ReferenceCode/Haswell/SampleCode/Library/Ksc/Smm/SmmKscLib.c
new file mode 100644
index 0000000..079482f
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/Ksc/Smm/SmmKscLib.c
@@ -0,0 +1,228 @@
+/** @file
+ SMM KSC library implementation.
+
+ These functions need to be SMM safe.
+
+ These functions require the SMM IO library (SmmIoLib) to be present.
+ Caller must link those libraries and have the proper include path.
+
+@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
+**/
+#include "KscLib.h"
+#include "SmmIoLib.h"
+#include "PchAccess.h"
+#include "PchPlatformLib.h"
+
+BOOLEAN mSmmKscLibInitialized = FALSE;
+
+///
+/// Function implemenations
+///
+/**
+ Initialize the library.
+ The SMM library only requires SMM IO library and has no initialization.
+ However, this must be called prior to use of any other KSC library functions
+ for future compatibility.
+
+ @param[in] None.
+
+ @retval EFI_SUCCESS - KscLib is successfully initialized.
+**/
+EFI_STATUS
+InitializeKscLib (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ ///
+ /// Fail if EC doesn't exist.
+ ///
+ if (SmmIoRead8 (KSC_C_PORT) == 0xff) {
+ mSmmKscLibInitialized = FALSE;
+ Status = EFI_DEVICE_ERROR;
+ } else {
+ mSmmKscLibInitialized = TRUE;
+ Status = EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+/**
+ Sends command to Keyboard System Controller.
+
+ @param[in] Command - Command byte to send
+
+ @retval EFI_SUCCESS - Command success
+ @retval EFI_DEVICE_ERROR - Command error
+**/
+EFI_STATUS
+SendKscCommand (
+ UINT8 Command
+ )
+{
+ UINTN Index;
+ UINT8 KscStatus;
+
+ KscStatus = 0;
+ ///
+ /// Verify if KscLib has been initialized, NOT if EC dose not exist.
+ ///
+ if (mSmmKscLibInitialized == FALSE) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Index = 0;
+
+ ///
+ /// Wait for KSC to be ready (with a timeout)
+ ///
+ ReceiveKscStatus (&KscStatus);
+ while (((KscStatus & KSC_S_IBF) != 0) && (Index < KSC_TIME_OUT)) {
+ PchPmTimerStall(15);
+ ReceiveKscStatus (&KscStatus);
+ Index++;
+ }
+
+ if (Index >= KSC_TIME_OUT) {
+ return EFI_DEVICE_ERROR;
+ }
+ ///
+ /// Send the KSC command
+ ///
+ SmmIoWrite8 (KSC_C_PORT, Command);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Receives status from Keyboard System Controller.
+
+ @param[in] KscStatus - Status byte to receive
+
+ @retval EFI_DEVICE_ERROR - Ksc library has not initialized yet or KSC not present
+ @retval EFI_SUCCESS - Get KSC status successfully
+**/
+EFI_STATUS
+ReceiveKscStatus (
+ UINT8 *KscStatus
+ )
+{
+ ///
+ /// Verify if KscLib has been initialized, NOT if EC dose not exist.
+ ///
+ if (mSmmKscLibInitialized == FALSE) {
+ return EFI_DEVICE_ERROR;
+ }
+ ///
+ /// Read and return the status
+ ///
+ *KscStatus = SmmIoRead8 (KSC_C_PORT);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Sends data to Keyboard System Controller.
+
+ @param[in] Data - Data byte to send
+
+ @retval EFI_SUCCESS - Success
+ @retval EFI_DEVICE_ERROR - Error
+**/
+EFI_STATUS
+SendKscData (
+ UINT8 Data
+ )
+{
+ UINTN Index;
+ UINT8 KscStatus;
+
+ ///
+ /// Verify if KscLib has been initialized, NOT if EC dose not exist.
+ ///
+ if (mSmmKscLibInitialized == FALSE) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Index = 0;
+
+ ///
+ /// Wait for KSC to be ready (with a timeout)
+ ///
+ ReceiveKscStatus (&KscStatus);
+ while (((KscStatus & KSC_S_IBF) != 0) && (Index < KSC_TIME_OUT)) {
+ PchPmTimerStall(15);
+ ReceiveKscStatus (&KscStatus);
+ Index++;
+ }
+
+ if (Index >= KSC_TIME_OUT) {
+ return EFI_DEVICE_ERROR;
+ }
+ ///
+ /// Send the data and return
+ ///
+ SmmIoWrite8 (KSC_D_PORT, Data);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Receives data from Keyboard System Controller.
+
+ @param[in] Data - Data byte received
+
+ @retval EFI_SUCCESS - Read success
+ @retval EFI_DEVICE_ERROR - Read error
+**/
+EFI_STATUS
+ReceiveKscData (
+ UINT8 *Data
+ )
+{
+ UINTN Index;
+ UINT8 KscStatus;
+
+ ///
+ /// Verify if KscLib has been initialized, NOT if EC dose not exist.
+ ///
+ if (mSmmKscLibInitialized == FALSE) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Index = 0;
+
+ ///
+ /// Wait for KSC to be ready (with a timeout)
+ ///
+ ReceiveKscStatus (&KscStatus);
+ while (((KscStatus & KSC_S_OBF) == 0) && (Index < KSC_TIME_OUT)) {
+ PchPmTimerStall(15);
+ ReceiveKscStatus (&KscStatus);
+ Index++;
+ }
+
+ if (Index >= KSC_TIME_OUT) {
+ return EFI_DEVICE_ERROR;
+ }
+ ///
+ /// Read KSC data and return
+ ///
+ *Data = SmmIoRead8 (KSC_D_PORT);
+
+ return EFI_SUCCESS;
+}
diff --git a/ReferenceCode/Haswell/SampleCode/Library/Ksc/Smm/SmmKscLib.cif b/ReferenceCode/Haswell/SampleCode/Library/Ksc/Smm/SmmKscLib.cif
new file mode 100644
index 0000000..3ee7072
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/Ksc/Smm/SmmKscLib.cif
@@ -0,0 +1,11 @@
+<component>
+ name = "SmmKscLib"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\SampleCode\Library\Ksc\Smm"
+ RefName = "SmmKscLib"
+[files]
+"SmmKscLib.sdl"
+"SmmKscLib.mak"
+"SmmKscLib.c"
+"SmmKscLib.inf"
+<endComponent>
diff --git a/ReferenceCode/Haswell/SampleCode/Library/Ksc/Smm/SmmKscLib.inf b/ReferenceCode/Haswell/SampleCode/Library/Ksc/Smm/SmmKscLib.inf
new file mode 100644
index 0000000..478ca1a
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/Ksc/Smm/SmmKscLib.inf
@@ -0,0 +1,51 @@
+## @file
+# Component description file.
+#
+#@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
+#
+
+
+[defines]
+BASE_NAME = SmmKscLib
+COMPONENT_TYPE = LIBRARY
+
+[sources.common]
+ SmmKscLib.c
+
+[includes.common]
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EFI_SOURCE)/Framework
+ .
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EFI_SOURCE)
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+ $(EDK_SOURCE)/Foundation
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/SampleCode/Include
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include/Library
+
+[libraries.common]
+ EdkFrameworkProtocolLib
+ PchPlatformLib
+
+[nmake.common]
+ C_STD_INCLUDE=
diff --git a/ReferenceCode/Haswell/SampleCode/Library/Ksc/Smm/SmmKscLib.mak b/ReferenceCode/Haswell/SampleCode/Library/Ksc/Smm/SmmKscLib.mak
new file mode 100644
index 0000000..ee3a5b0
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/Ksc/Smm/SmmKscLib.mak
@@ -0,0 +1,15 @@
+# MAK file for the ModulePart:CpuPlatformLib
+
+$(SmmKscLib_LIB) : SmmKscLib
+
+SmmKscLib : $(BUILD_DIR)\SmmKscLib.mak SmmKscLibBin
+
+$(BUILD_DIR)\SmmKscLib.mak : $(SmmKscLib_DIR)\$(@B).cif $(SmmKscLib_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(SmmKscLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+SmmKscLibBin :
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ BUILD_DIR=$(BUILD_DIR) \
+ /f $(BUILD_DIR)\SmmKscLib.mak all\
+ "MY_INCLUDES=$(EDK_INCLUDES) $(EdkIIGlueLib_INCLUDES) $(PROJECT_CPU_INCLUDES)" \
+ TYPE=LIBRARY "PARAMETERS=LIBRARY_NAME=$$(SmmKscLib_LIB)" \ No newline at end of file
diff --git a/ReferenceCode/Haswell/SampleCode/Library/Ksc/Smm/SmmKscLib.sdl b/ReferenceCode/Haswell/SampleCode/Library/Ksc/Smm/SmmKscLib.sdl
new file mode 100644
index 0000000..46ce94f
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/Ksc/Smm/SmmKscLib.sdl
@@ -0,0 +1,25 @@
+TOKEN
+ Name = SmmKscLib_SUPPORT
+ Value = 1
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+ Help = "Main switch to enable SmmKscLib support in Project"
+End
+
+TOKEN
+ Name = "SmmKscLib_LIB"
+ Value = "$$(LIB_BUILD_DIR)\SmmKscLib.lib"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+MODULE
+ Help = "Includes SmmKscLib.mak to Project"
+ File = "SmmKscLib.mak"
+End
+
+PATH
+ Name = "SmmKscLib_DIR"
+End \ No newline at end of file
diff --git a/ReferenceCode/Haswell/SampleCode/Library/SmmIo/SmmIo.c b/ReferenceCode/Haswell/SampleCode/Library/SmmIo/SmmIo.c
new file mode 100644
index 0000000..9f1e19d
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/SmmIo/SmmIo.c
@@ -0,0 +1,169 @@
+/** @file
+ SMM I/O access utility implementation file, for Ia32
+
+@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
+**/
+
+///
+/// Include files
+///
+#include "SmmIoLib.h"
+
+/**
+ Do a one byte IO read
+
+ @param[in] Address - IO address to read
+
+ @retval Data read
+**/
+UINT8
+SmmIoRead8 (
+ IN UINT16 Address
+ )
+{
+ UINT8 Buffer;
+
+ ASSERT (mSmst);
+
+ mSmst->SmmIo.Io.Read (
+ &mSmst->SmmIo,
+ SMM_IO_UINT8,
+ Address,
+ 1,
+ &Buffer
+ );
+ return Buffer;
+}
+
+/**
+ Do a one byte IO write
+
+ @param[in] Address - IO address to write
+ @param[in] Data - Data to write
+**/
+VOID
+SmmIoWrite8 (
+ IN UINT16 Address,
+ IN UINT8 Data
+ )
+{
+ ASSERT (mSmst);
+
+ mSmst->SmmIo.Io.Write (
+ &mSmst->SmmIo,
+ SMM_IO_UINT8,
+ Address,
+ 1,
+ &Data
+ );
+}
+
+/**
+ Do a two byte IO read
+
+ @param[in] Address - IO address to read
+
+ @retval Data read
+**/
+UINT16
+SmmIoRead16 (
+ IN UINT16 Address
+ )
+{
+ UINT16 Buffer;
+
+ ASSERT (mSmst);
+
+ mSmst->SmmIo.Io.Read (
+ &mSmst->SmmIo,
+ SMM_IO_UINT16,
+ Address,
+ 1,
+ &Buffer
+ );
+ return Buffer;
+}
+
+/**
+ Do a two byte IO write
+
+ @param[in] Address - IO address to write
+ @param[in] Data - Data to write
+**/
+VOID
+SmmIoWrite16 (
+ IN UINT16 Address,
+ IN UINT16 Data
+ )
+{
+ ASSERT (mSmst);
+
+ mSmst->SmmIo.Io.Write (
+ &mSmst->SmmIo,
+ SMM_IO_UINT16,
+ Address,
+ 1,
+ &Data
+ );
+}
+
+/**
+ Do a four byte IO read
+
+ @param[in] Address - IO address to read
+
+ @retval Data read
+**/
+UINT32
+SmmIoRead32 (
+ IN UINT16 Address
+ )
+{
+ UINT32 Buffer;
+
+ ASSERT (mSmst);
+
+ mSmst->SmmIo.Io.Read (
+ &mSmst->SmmIo,
+ SMM_IO_UINT32,
+ Address,
+ 1,
+ &Buffer
+ );
+ return Buffer;
+}
+
+/**
+ Do a four byte IO write
+
+ @param[in] Address - IO address to write
+ @param[in] Data - Data to write
+**/
+VOID
+SmmIoWrite32 (
+ IN UINT16 Address,
+ IN UINT32 Data
+ )
+{
+ ASSERT (mSmst);
+
+ mSmst->SmmIo.Io.Write (
+ &mSmst->SmmIo,
+ SMM_IO_UINT32,
+ Address,
+ 1,
+ &Data
+ );
+}
diff --git a/ReferenceCode/Haswell/SampleCode/Library/SmmIo/SmmIoLib.cif b/ReferenceCode/Haswell/SampleCode/Library/SmmIo/SmmIoLib.cif
new file mode 100644
index 0000000..ec8cae7
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/SmmIo/SmmIoLib.cif
@@ -0,0 +1,12 @@
+<component>
+ name = "SmmIoLib"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\SampleCode\Library\SmmIo"
+ RefName = "SmmIoLib"
+[files]
+"SmmIoLib.sdl"
+"SmmIoLib.mak"
+"SmmIoLib.inf"
+"SmmIo.c"
+"SmmPciIo.c"
+<endComponent>
diff --git a/ReferenceCode/Haswell/SampleCode/Library/SmmIo/SmmIoLib.inf b/ReferenceCode/Haswell/SampleCode/Library/SmmIo/SmmIoLib.inf
new file mode 100644
index 0000000..43045eb
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/SmmIo/SmmIoLib.inf
@@ -0,0 +1,48 @@
+## @file
+# Component description file.
+#
+#@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
+#
+
+
+[defines]
+BASE_NAME = SmmIoLib
+COMPONENT_TYPE = LIBRARY
+
+[sources.common]
+ SmmIo.c
+ SmmPciIo.c
+
+[includes.common]
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EFI_SOURCE)/Framework
+ .
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EFI_SOURCE)
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+ $(EDK_SOURCE)/Foundation
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/SampleCode/Include
+
+[libraries.common]
+ EdkFrameworkProtocolLib
+
+[nmake.common]
diff --git a/ReferenceCode/Haswell/SampleCode/Library/SmmIo/SmmIoLib.mak b/ReferenceCode/Haswell/SampleCode/Library/SmmIo/SmmIoLib.mak
new file mode 100644
index 0000000..12b9d5e
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/SmmIo/SmmIoLib.mak
@@ -0,0 +1,15 @@
+# MAK file for the ModulePart:CpuPlatformLib
+
+$(SmmIoLib_LIB) : SmmIoLib
+
+SmmIoLib : $(BUILD_DIR)\SmmIoLib.mak SmmIoLibBin
+
+$(BUILD_DIR)\SmmIoLib.mak : $(SmmIoLib_DIR)\$(@B).cif $(SmmIoLib_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(SmmIoLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+SmmIoLibBin :
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ BUILD_DIR=$(BUILD_DIR) \
+ /f $(BUILD_DIR)\SmmIoLib.mak all\
+ "MY_INCLUDES=$(EDK_INCLUDES) $(EdkIIGlueLib_INCLUDES) $(PROJECT_CPU_INCLUDES)" \
+ TYPE=LIBRARY "PARAMETERS=LIBRARY_NAME=$$(SmmIoLib_LIB)" \ No newline at end of file
diff --git a/ReferenceCode/Haswell/SampleCode/Library/SmmIo/SmmIoLib.sdl b/ReferenceCode/Haswell/SampleCode/Library/SmmIo/SmmIoLib.sdl
new file mode 100644
index 0000000..537a750
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/SmmIo/SmmIoLib.sdl
@@ -0,0 +1,25 @@
+TOKEN
+ Name = SmmIoLib_SUPPORT
+ Value = 1
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+ Help = "Main switch to enable SmmIoLib support in Project"
+End
+
+TOKEN
+ Name = "SmmIoLib_LIB"
+ Value = "$$(LIB_BUILD_DIR)\SmmIoLib.lib"
+ TokenType = Expression
+ TargetMAK = Yes
+End
+
+MODULE
+ Help = "Includes SmmIoLib.mak to Project"
+ File = "SmmIoLib.mak"
+End
+
+PATH
+ Name = "SmmIoLib_DIR"
+End \ No newline at end of file
diff --git a/ReferenceCode/Haswell/SampleCode/Library/SmmIo/SmmPciIo.c b/ReferenceCode/Haswell/SampleCode/Library/SmmIo/SmmPciIo.c
new file mode 100644
index 0000000..f6fd18f
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Library/SmmIo/SmmPciIo.c
@@ -0,0 +1,161 @@
+/** @file
+ SMM PCI config space I/O access utility implementation file, for Ia32
+
+@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 "SmmIoLib.h"
+
+STATIC
+EFI_STATUS
+SmmSingleSegmentPciAccess (
+ IN EFI_SMM_CPU_IO_INTERFACE *CpuIo,
+ IN BOOLEAN IsWrite,
+ IN SMM_PCI_IO_WIDTH Width,
+ IN SMM_PCI_IO_ADDRESS *Address,
+ IN OUT VOID *Buffer
+ );
+
+/**
+ Read value from the specified PCI config space register
+
+ @param[in] Width - The width (8, 16 or 32 bits) of accessed pci config space register
+ @param[in] Address - The address of the accessed pci register (bus, dev, func, offset)
+ @param[in] Buffer - The returned value
+
+ @retval EFI_SUCCESS - All operations successfully
+ @retval EFI_INVALID_PARAMETER - Width is not valid or dosn't match register address
+ @retval Other error code - If any error occured when calling libiary functions
+**/
+EFI_STATUS
+SmmPciCfgRead (
+ IN SMM_PCI_IO_WIDTH Width,
+ IN SMM_PCI_IO_ADDRESS *Address,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_SMM_CPU_IO_INTERFACE *SmmCpuIo;
+
+ ASSERT (mSmst);
+
+ SmmCpuIo = &(mSmst->SmmIo);
+
+ return SmmSingleSegmentPciAccess (SmmCpuIo, FALSE, Width, Address, Buffer);
+}
+
+/**
+ Write value into the specified PCI config space register
+
+ @param[in] Width - The width (8, 16 or 32 bits) of accessed pci config space register
+ @param[in] Address - The address of the accessed pci register (bus, dev, func, offset)
+ @param[in] Buffer - The returned value
+
+ @retval EFI_SUCCESS - All operations successfully
+ @retval EFI_INVALID_PARAMETER - Width is not valid or dosn't match register address
+ @retval Other error code - If any error occured when calling libiary functions
+**/
+EFI_STATUS
+SmmPciCfgWrite (
+ IN SMM_PCI_IO_WIDTH Width,
+ IN SMM_PCI_IO_ADDRESS *Address,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_SMM_CPU_IO_INTERFACE *SmmCpuIo;
+
+ ASSERT (mSmst);
+
+ SmmCpuIo = &(mSmst->SmmIo);
+
+ return SmmSingleSegmentPciAccess (SmmCpuIo, TRUE, Width, Address, Buffer);
+}
+
+/**
+ Access a PCI config space address, including read and write
+
+ @param[in] CpuIo - The cpu I/O accessing interface provided by EFI runtime sys table
+ @param[in] IsWrite - Indicates whether this operation is a write access or read
+ @param[in] Width - The width (8, 16 or 32 bits) of accessed pci config space register
+ @param[in] Address - The address of the accessed pci register (bus, dev, func, offset)
+ @param[in] Buffer - The returned value when this is a reading operation or the data
+ to be written when this is a writing one
+
+ @retval EFI_SUCCESS - All operations successfully
+ @retval EFI_INVALID_PARAMETER - Width is not valid or dosn't match register address
+ @retval Other error code - If any error occured when calling libiary functions
+**/
+STATIC
+EFI_STATUS
+SmmSingleSegmentPciAccess (
+ IN EFI_SMM_CPU_IO_INTERFACE *CpuIo,
+ IN BOOLEAN IsWrite,
+ IN SMM_PCI_IO_WIDTH Width,
+ IN SMM_PCI_IO_ADDRESS *Address,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ PCI_CONFIG_ACCESS_CF8 PciCf8Data;
+ UINT64 PciDataReg;
+
+ ///
+ /// PCI Config access are all 32-bit alligned, but by accessing the
+ /// CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types
+ /// are possible on PCI.
+ ///
+ /// To read a byte of PCI config space you load 0xcf8 and
+ /// read 0xcfc, 0xcfd, 0xcfe, 0xcff
+ ///
+ /// The validation of passed in arguments "Address" will be checked in the
+ /// CPU IO functions, so we don't check them here
+ ///
+ if (Width >= SmmPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PciCf8Data.Reg = Address->Register & 0xfc;
+ PciCf8Data.Func = Address->Function;
+ PciCf8Data.Dev = Address->Device;
+ PciCf8Data.Bus = Address->Bus;
+ PciCf8Data.Reserved = 0;
+ PciCf8Data.Enable = 1;
+
+ Status = CpuIo->Io.Write (CpuIo, SmmPciWidthUint32, 0xcf8, 1, &PciCf8Data);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ PciDataReg = 0xcfc + (Address->Register & 0x03);
+
+ if (IsWrite) {
+ ///
+ /// This is a Pci write operation, write data into (0xcfc + offset)
+ ///
+ Status = CpuIo->Io.Write (CpuIo, Width, PciDataReg, 1, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ } else {
+ ///
+ /// This is a Pci Read operation, read returned data from (0xcfc + offset)
+ ///
+ Status = CpuIo->Io.Read (CpuIo, Width, PciDataReg, 1, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/ReferenceCode/Haswell/SampleCode/Protocol/CpuSampleCodeProtocolLib.cif b/ReferenceCode/Haswell/SampleCode/Protocol/CpuSampleCodeProtocolLib.cif
new file mode 100644
index 0000000..96d3f7b
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Protocol/CpuSampleCodeProtocolLib.cif
@@ -0,0 +1,11 @@
+<component>
+ name = "CpuSampleCodeProtocolLib"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\SampleCode\Protocol\"
+ RefName = "CpuSampleCodeProtocolLib"
+[files]
+"CpuSampleCodeProtocolLib.mak"
+"CpuSampleCodeProtocolLib.sdl"
+"TxtOneTouchOp\TxtOneTouchOp.c"
+"TxtOneTouchOp\TxtOneTouchOp.h"
+<endComponent>
diff --git a/ReferenceCode/Haswell/SampleCode/Protocol/CpuSampleCodeProtocolLib.mak b/ReferenceCode/Haswell/SampleCode/Protocol/CpuSampleCodeProtocolLib.mak
new file mode 100644
index 0000000..f77edb4
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Protocol/CpuSampleCodeProtocolLib.mak
@@ -0,0 +1,25 @@
+all : CpuSampleCodeProtocolLib
+
+$(CpuSampleCodeProtocolLib_LIB) : CpuSampleCodeProtocolLib
+
+CpuSampleCodeProtocolLib : $(BUILD_DIR)\CpuSampleCodeProtocolLib.mak CpuSampleCodeProtocolLibBin
+
+$(BUILD_DIR)\CpuSampleCodeProtocolLib.mak : $(CpuSampleCodeProtocolLib_DIR)\$(@B).cif $(CpuSampleCodeProtocolLib_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(CpuSampleCodeProtocolLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+CpuSampleCodeProtocolLib_INCLUDES=\
+ $(EDK_INCLUDES)\
+ $(EdkIIGlueLib_INCLUDES)\
+ $(PROJECT_CPU_INCLUDES)\
+
+CpuSampleCodeProtocolLibBin :
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\CpuSampleCodeProtocolLib.mak all\
+ "MY_INCLUDES=$(CpuSampleCodeProtocolLib_INCLUDES)" \
+ TYPE=LIBRARY
+!IF "$(x64_BUILD)"=="1"
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS) BUILD_DIR=$(BUILD_DIR)\IA32\
+ /f $(BUILD_DIR)\CpuSampleCodeProtocolLib.mak all\
+ "MY_INCLUDES=$(CpuSampleCodeProtocolLib_INCLUDES)" \
+ TYPE=PEI_LIBRARY
+!ENDIF \ No newline at end of file
diff --git a/ReferenceCode/Haswell/SampleCode/Protocol/CpuSampleCodeProtocolLib.sdl b/ReferenceCode/Haswell/SampleCode/Protocol/CpuSampleCodeProtocolLib.sdl
new file mode 100644
index 0000000..6662a1b
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Protocol/CpuSampleCodeProtocolLib.sdl
@@ -0,0 +1,24 @@
+TOKEN
+ Name = "CpuSampleCodeProtocolLib_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable CpuSampleCodeProtocolLib support in Project"
+ TokenType = Boolean
+ TargetMAK = Yes
+ Master = Yes
+End
+
+PATH
+ Name = "CpuSampleCodeProtocolLib_DIR"
+End
+
+MODULE
+ Help = "Includes CpuSampleCodeProtocolLib.mak to Project"
+ File = "CpuSampleCodeProtocolLib.mak"
+End
+
+TOKEN
+ Name = "CpuSampleCodeProtocolLib_LIB"
+ Value = "$$(LIB_BUILD_DIR)\CpuSampleCodeProtocolLib.lib"
+ TokenType = Expression
+ TargetMAK = Yes
+End \ No newline at end of file
diff --git a/ReferenceCode/Haswell/SampleCode/Protocol/TxtOneTouchOp/TxtOneTouchOp.c b/ReferenceCode/Haswell/SampleCode/Protocol/TxtOneTouchOp/TxtOneTouchOp.c
new file mode 100644
index 0000000..3e6f982
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Protocol/TxtOneTouchOp/TxtOneTouchOp.c
@@ -0,0 +1,32 @@
+/** @file
+ Txt specific PPI operation definition.
+
+@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
+**/
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#endif
+#include "TxtOneTouchOp.h"
+
+///
+/// Protocol GUID definition
+///
+EFI_GUID gTxtOneTouchOpProtocolGuid = TXT_ONE_TOUCH_OP_PROTOCOL_GUID;
+
+///
+/// Protocol description
+///
+EFI_GUID_STRING(&gTxtOneTouchOpProtocolGuid, "Txt One Touch OP Protocol", "Txt One Touch OP Protocol");
diff --git a/ReferenceCode/Haswell/SampleCode/Protocol/TxtOneTouchOp/TxtOneTouchOp.h b/ReferenceCode/Haswell/SampleCode/Protocol/TxtOneTouchOp/TxtOneTouchOp.h
new file mode 100644
index 0000000..aaccb4e
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/Protocol/TxtOneTouchOp/TxtOneTouchOp.h
@@ -0,0 +1,106 @@
+/** @file
+ Txt specific PPI operation definition.
+
+@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
+**/
+#ifndef _TXT_PPI_OPERATION_H_
+#define _TXT_PPI_OPERATION_H_
+
+///
+/// EDK and EDKII have different GUID formats
+///
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#define TXT_ONE_TOUCH_OP_PROTOCOL_GUID \
+ { \
+ 0xFA2338AD, 0x80DF, 0x49D0, 0x93, 0x96, 0xCF, 0x71, 0x45, 0xD0, 0x3A, 0x76 \
+ }
+#else
+#define TXT_ONE_TOUCH_OP_PROTOCOL_GUID \
+ { \
+ 0xFA2338AD, 0x80DF, 0x49D0, \
+ { \
+ 0x93, 0x96, 0xCF, 0x71, 0x45, 0xD0, 0x3A, 0x76 \
+ } \
+ }
+#endif
+///
+/// Extern the GUID for protocol users.
+///
+extern EFI_GUID gTxtOneTouchOpProtocolGuid;
+
+///
+/// Forward reference for ANSI C compatibility
+///
+typedef struct _TXT_ONE_TOUCH_OP_PROTOCOL TXT_ONE_TOUCH_OP_PROTOCOL;
+
+///
+/// Member functions
+///
+typedef
+EFI_STATUS
+(EFIAPI *TXT_PPI_EXEC_OPERATION)(
+ IN TXT_ONE_TOUCH_OP_PROTOCOL *This,
+ IN UINT8 Command
+ );
+
+/*
+
+@brief
+ Extend PPI operation for TxT.
+
+ @param[in] This - Point of TXT_ONE_TOUCH_OP_PROTOCOL
+ @param[in] Command - Operation value for TxT
+
+*/
+typedef
+EFI_STATUS
+(EFIAPI *TXT_CONFIRMATION_DIALOG)(
+ IN TXT_ONE_TOUCH_OP_PROTOCOL *This,
+ IN UINT8 Command,
+ IN OUT BOOLEAN *Confirm
+ );
+/*
+
+@brief
+ Confirmation dialog for TxT PPI
+
+ @param[in] This - Point of TXT_ONE_TOUCH_OP_PROTOCOL
+ @param[in] Command - Operation value for TxT
+ @param[in] Confirm - User confirm
+
+*/
+typedef
+EFI_STATUS
+(EFIAPI *TXT_RESET_SYSTEM)(
+ IN TXT_ONE_TOUCH_OP_PROTOCOL *This,
+ IN UINT8 Command
+ );
+
+/**
+ Reset system.
+
+ @param[in] This - Point of TXT_ONE_TOUCH_OP_PROTOCOL
+ @param[in] Command - Operation value for TxT
+
+ @retval EFI_SUCCESS - Always return EFI_SUCCESS
+**/
+struct _TXT_ONE_TOUCH_OP_PROTOCOL {
+ TXT_PPI_EXEC_OPERATION ExecuteOperation;
+ TXT_CONFIRMATION_DIALOG ConfirmationDialog;
+ TXT_RESET_SYSTEM ResetSystem;
+};
+
+#endif
diff --git a/ReferenceCode/Haswell/SampleCode/SecCore/CpuRcSec.cif b/ReferenceCode/Haswell/SampleCode/SecCore/CpuRcSec.cif
new file mode 100644
index 0000000..0bc0424
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/SecCore/CpuRcSec.cif
@@ -0,0 +1,20 @@
+<component>
+ name = "CpuRcSec"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\SampleCode\SecCore"
+ RefName = "CpuRcSec"
+[files]
+"CpuRcSec.mak"
+"CpuRcSec.sdl"
+"Sec\Ia32\Chipset.inc"
+"Sec\Ia32\CpuRcSec.asm"
+"Sec\Ia32\CrcSecPpi.c"
+"Sec\Ia32\Flat32.asm"
+"Sec\Ia32\Ia32.inc"
+"Sec\Ia32\SecFlat32.inc"
+"Sec\Ia32\Platform.inc"
+"Sec\Ia32\ResetVec.asm"
+"Sec\Ia32\ResetVec.raw"
+"Sec\Ia32\SecCore.inc"
+"Sec\Ia32\SecStartup.c"
+<endComponent>
diff --git a/ReferenceCode/Haswell/SampleCode/SecCore/CpuRcSec.mak b/ReferenceCode/Haswell/SampleCode/SecCore/CpuRcSec.mak
new file mode 100644
index 0000000..8f1b13f
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/SecCore/CpuRcSec.mak
@@ -0,0 +1,27 @@
+# MAK file for the ModulePart:CPU SEC RC
+CPU_RC_DEPENDANCIES = \
+$(CPU_RC_SEC_DIR)\Platform.inc \
+$(CPU_RC_SEC_DIR)\Chipset.inc \
+$(CPU_RC_SEC_DIR)\SecFlat32.inc
+
+$(BUILD_DIR)\CpuRcSec.obj : $(CPU_RC_SEC_DIR)\CpuRcSec.asm $(CPU_RC_DEPENDANCIES)
+ $(ASM) /c /nologo /coff /Sa /I$(BUILD_DIR) /Fo$@ $(CPU_RC_SEC_DIR)\CpuRcSec.asm
+
+
+# Add its own include path to
+MY_INC = \
+/ICore \
+/IEDK\Foundation\Framework\Ppi\SecPlatformInformation
+
+# Add CrcSecPpi.obj to CORE_PEIBin dependency list, so it will be linked with PEI CORE
+CORE_PEIBin: $(BUILD_DIR)\CrcSecPpi.obj
+# Add SecPlatformInformation.obj to CORE_PEIBin dependency list, so it will be linked with PEI CORE
+CORE_PEIBin: $(BUILD_DIR)\SecPlatformInformation.obj
+
+# Add a description block for CrcSecPpi.OBJ for cross-module link
+$(BUILD_DIR)\CrcSecPpi.OBJ : $(CPU_RC_SEC_DIR)\CrcSecPpi.c
+ $(CC) $(CFLAGS) $(MY_INC) /Fo$(BUILD_DIR)\CrcSecPpi.obj $(CPU_RC_SEC_DIR)\CrcSecPpi.c
+
+# Add a description block for SecPlatformInformation.OBJ
+$(BUILD_DIR)\SecPlatformInformation.obj : $(EdkFrameworkPpiLib_DIR)\SECPLATFORMINFORMATION\SecPlatformInformation.c
+ $(CC) $(CFLAGS) $(EDK_INCLUDES) /D TIANO_RELEASE_VERSION=0x00080006 /Fo$(BUILD_DIR)\SecPlatformInformation.obj $(EdkFrameworkPpiLib_DIR)\SECPLATFORMINFORMATION\SecPlatformInformation.c
diff --git a/ReferenceCode/Haswell/SampleCode/SecCore/CpuRcSec.sdl b/ReferenceCode/Haswell/SampleCode/SecCore/CpuRcSec.sdl
new file mode 100644
index 0000000..3c8a5b0
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/SecCore/CpuRcSec.sdl
@@ -0,0 +1,40 @@
+TOKEN
+ Name = "Intel_Haswell_SEC_RC_SUPPORT"
+ Value = "1"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+End
+
+MODULE
+ Help = "Includes CpuRcSec.mak to Project"
+ File = "CpuRcSec.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\CpuRcSec.obj"
+ Parent = "ADDON_SEC_CORE_OBJ_FILES"
+ InvokeOrder = AfterParent
+End
+
+PATH
+ Name = "CPU_RC_SEC_DIR"
+ Path = "ReferenceCode\Haswell\SampleCode\SecCore\Sec\Ia32"
+End
+
+ELINK
+ Name = "GainestownSecRcEntry"
+ Parent = "SECCoreAtPowerOn"
+ Priority = 1000
+ Help = "Gainestown RC"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "CrcSecPlatformInformationPpi,"
+ Parent = "PeiCoreInitialize"
+ InvokeOrder = AfterParent
+End
+
diff --git a/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/Chipset.inc b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/Chipset.inc
new file mode 100644
index 0000000..ebd52ab
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/Chipset.inc
@@ -0,0 +1,107 @@
+;@file
+; Chipset constants and macros
+;
+;@copyright
+; Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved
+; This software and associated documentation (if any) is furnished
+; under a license and may only be used or copied in accordance
+; with the terms of the license. Except as permitted by such
+; license, no part of this software or documentation may be
+; reproduced, stored in a retrieval system, or transmitted in any
+; form or by any means without the express written consent of
+; Intel Corporation.
+;
+; This file contains a 'Sample Driver' and is licensed as such
+; under the terms of your license agreement with Intel or your
+; vendor. This file may be modified by the user, subject to
+; the additional terms of the license agreement
+;
+
+;
+; APIC register
+;
+APICID EQU 0FEE00020h
+
+;
+; Power Management I/O Registers
+;
+PCH_ACPI_BASE_ADDRESS EQU 0500h
+ACPI_PM1_STS EQU 000h
+ACPI_PM1_CNT EQU 004h
+
+;
+; PCH RCBA base address
+;
+PCH_RCRB_BASE EQU 0FED1C000h
+PCH_RCRB_BASE_REG EQU 8000F8F0h ; PCH Register B0:D31:RF0
+PCH_RCRB_GCS EQU 03410h
+PCH_RCRB_RTC_CONF EQU 03400h
+PCH_RCRB_RTC_CONF_UCMOS_EN EQU 04h
+PCH_RCRB_HPET EQU 03404h
+PCH_RCRB_HPET_DECODE EQU 080h
+
+;
+; HPET compare register
+;
+HPET_COMP_1 EQU 0FED00108h
+HPET_COMP_2 EQU 0FED0010Ch
+HPET_COMP_3 EQU 0FED00128h
+HPET_COMP_4 EQU 0FED00148h
+
+;
+; MCH PCIe base address
+;
+;Need to match PcdPciExpressBaseAddress or PCIEX_BASE_ADDRESS
+;CPU_HEC_BASE EQU 0E0000000h ; Must be X0000000
+;(AMI_CHG)>
+CPU_HEC_BASE EQU MKF_PCIEX_BASE_ADDRESS ; Must be X0000000
+;<(AMI_CHG)
+;CPU_HEC_SIZE EQU 000000000h ; 256M
+;(AMI_CHG)>
+CPU_HEC_SIZE EQU MKF_PCIEX_LENGTH_BIT_SETTING ; 64M, 128M, 256M
+;<(AMI_CHG)
+CPU_HEC_EN EQU 000000001h ; Enable
+CPU0_HEC_PCI_ADDR EQU 080FF0150h
+CPU1_HEC_PCI_ADDR EQU 080FE0150h
+
+PCI_LPC_BASE EQU 08000F800h
+
+GPIO_BASE_ADDRESS EQU 0800h
+R_GPIO_USE_SEL2 EQU 030h
+R_GPIO_IO_SEL2 EQU 034h
+R_GPIO_LVL2 EQU 038h
+
+;
+; PCI registers
+;
+PCH_LPC_PMBASE_PCI_ADDR EQU ((1Fh * 8 + 00h) * 1000h + 0040h + CPU_HEC_BASE)
+PCH_LPC_ACPICNTL_PCI_ADDR EQU ((1Fh * 8 + 00h) * 1000h + 0044h + CPU_HEC_BASE)
+PCH_LPC_GEN_PMCON_3_ADDR EQU ((1Fh * 8 + 00h) * 1000h + 00A4h + CPU_HEC_BASE)
+PCH_LPC_RCRB_PCI_ADDR EQU ((1Fh * 8 + 00h) * 1000h + 00F0h + CPU_HEC_BASE)
+PCH_LPC_BIOS_CNTL_PCI_ADDR EQU ((1Fh * 8 + 00h) * 1000h + 00DCh + CPU_HEC_BASE)
+MCH_UNCERRMASK_PCI_ADDR EQU ((00h * 8 + 00h) * 1000h + 0108h + CPU_HEC_BASE)
+MCH_SYRE_PCI_ADDR EQU ((10h * 8 + 00h) * 1000h + 0040h + CPU_HEC_BASE)
+
+SYRE_CPURST EQU 14
+
+;
+; PCIEXBAR constants for enable in bit [0]
+;
+ENABLE EQU 1
+
+;
+; PCIEXBAR constants for size in bit [2:1]
+;
+PCIEXBAR_64MB EQU 010b
+PCIEXBAR_128MB EQU 001b
+PCIEXBAR_256MB EQU 000b
+
+MMCFG_BASE EQU CPU_HEC_BASE ; 4GB-128MB
+MMCFG_LENGTH_BIT_SETTING EQU CPU_HEC_SIZE ; 64M, 128M, 256M
+
+DMIBAR_REG EQU (068h + CPU_HEC_BASE)
+DMI_BASE_ADDRESS EQU 0FED18000h
+
+MCHBAR_REG EQU (048h + CPU_HEC_BASE)
+MCH_BASE_ADDRESS EQU 0FED10000h
+
diff --git a/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/CpuRcSec.asm b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/CpuRcSec.asm
new file mode 100644
index 0000000..1460ddf
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/CpuRcSec.asm
@@ -0,0 +1,38 @@
+
+ INCLUDE Token.equ
+ INCLUDE Platform.inc
+ INCLUDE Ia32.inc
+
+CPU_HEC_BASE EQU MKF_PCIEX_BASE_ADDRESS ; Must defined before include Chipset.inc
+ INCLUDE Chipset.inc
+
+ INCLUDE SecCore.inc
+
+ .686p
+ .xmm
+ .model small
+
+ extern FindMicrocode:NEAR32
+ extern GainestownSecRcEntryEnd:NEAR32
+
+STARTUP_SEG SEGMENT PARA PUBLIC USE32 'CODE'
+ ASSUME CS:STARTUP_SEG, DS:STARTUP_SEG
+
+ INCLUDE SecFlat32.inc
+
+GainestownSecRcEntry PROC
+
+ jmp ProtectedModeSECStart ; Jump to IvyBridge SEC sample code
+
+CallPeiCoreEntryPoint PROC
+ ; Set stack top pointer
+ mov esp, DATA_STACK_BASE_ADDRESS + DATA_STACK_SIZE
+
+ jmp GainestownSecRcEntryEnd ; Exit the eLink
+CallPeiCoreEntryPoint ENDP
+
+GainestownSecRcEntry ENDP
+
+STARTUP_SEG ENDS
+END
+
diff --git a/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/CrcSecPpi.c b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/CrcSecPpi.c
new file mode 100644
index 0000000..28cc105
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/CrcSecPpi.c
@@ -0,0 +1,233 @@
+/*++
+ This file contains an 'Intel Peripheral Driver' and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+--*/
+/*++
+
+Copyright (c) 1999 - 2008 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ CrcSecPpi.c
+
+Abstract:
+
+ Install SecPlatformInformation PPI.
+
+--*/
+
+//#include "Tiano.h"
+//#include "PeiCore.h"
+//#include "FlashMap.h"
+//#include "EfiFirmwareFileSystem.h"
+//#include "EfiFirmwareVolumeHeader.h"
+
+//#include EFI_PPI_DEFINITION (SecPlatformInformation)
+#include "Tiano.h"
+//#include <Core\Core_Pei\PeiCore.h>
+
+//#include "Efi.h"
+//#include "Pei.h"
+
+#include "EfiCommonLib.h"
+#include <Ppi\AmiEarlyBistPpi.h>
+static EFI_GUID gAmiEarlyBistGuid = AMI_EARLY_BIST_PPI_GUID;
+
+#include "SecPlatformInformation.h"
+
+EFI_STATUS
+SecPlatformInformation (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT UINT64 *StructureSize,
+ IN OUT SEC_PLATFORM_INFORMATION_RECORD *PlatformInformationRecord
+ );
+
+EFI_SEC_PLATFORM_INFORMATION_PPI mSecPlatformInformationPpi = { SecPlatformInformation };
+
+EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformationPpi = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiSecPlatformInformationPpiGuid,
+ &mSecPlatformInformationPpi
+};
+
+EFI_STATUS
+EFIAPI
+SecPlatformInformation (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN OUT UINT64 *StructureSize,
+ IN OUT SEC_PLATFORM_INFORMATION_RECORD *PlatformInformationRecord
+ )
+/*++
+
+Routine Description:
+
+ Implementation of the PlatformInformation service in
+ EFI_SEC_PLATFORM_INFORMATION_PPI.
+ This function conveys state information out of the SEC phase into PEI.
+
+Arguments:
+
+ PeiServices - Pointer to the PEI Services Table.
+ StructureSize - Pointer to the variable describing size of the input buffer.
+ PlatformInformationRecord - Pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD.
+
+Returns:
+
+ EFI_SUCCESS - The data was successfully returned.
+ EFI_BUFFER_TOO_SMALL - The buffer was too small.
+
+--*/
+{
+ UINT32 *BIST;
+ UINT32 Size;
+ UINT32 Count;
+ AMI_EARLY_BIST_PPI *AmiEarlyPpi;
+ EFI_STATUS Status;
+ CPU_BIST PrivateBist;
+
+ Status = (*PeiServices)->LocatePpi(
+ PeiServices,
+ &gAmiEarlyBistGuid,
+ 0, NULL,
+ &AmiEarlyPpi
+ );
+ //Force BIST no error if PPI not found
+ if (Status != EFI_SUCCESS) {
+ Size = sizeof (UINT64);
+ if ((*StructureSize) < (UINT64) Size) {
+ *StructureSize = Size;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ PrivateBist.ApicId = 0;
+ PrivateBist.Bist = 0;
+ BIST = (UINT32*)&PrivateBist;
+ } else{
+ Count = AmiEarlyPpi->NumBists;
+ Size = Count * sizeof (UINT64);
+ if ((*StructureSize) < (UINT64) Size) {
+ *StructureSize = Size;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ BIST = (UINT32 *) (&(AmiEarlyPpi->CpuBist));
+ }
+ *StructureSize = Size;
+ EfiCommonLibCopyMem (PlatformInformationRecord, BIST, Size);
+
+ return EFI_SUCCESS;
+
+/*
+ UINT32 *BIST;
+ UINT32 Size;
+ UINT32 Count;
+
+ //
+ // The entries of BIST information, together with the number of them,
+ // reside in the bottom of stack, left untouched by normal stack operation.
+ // This routine copies the BIST information to the buffer pointed by
+ // PlatformInformationRecord for output.
+ //
+ Count = *(TopOfCar - 1);
+ Size = Count * sizeof (UINT64);
+
+ if ((*StructureSize) < (UINT64) Size) {
+ *StructureSize = Size;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ *StructureSize = Size;
+ BIST = (UINT32 *) ((UINT32) TopOfCar - sizeof (UINT32) - Size);
+
+ EfiCommonLibCopyMem (PlatformInformationRecord, BIST, Size);
+
+ return EFI_SUCCESS;
+*/
+}
+
+//<AMI_PHDR_START>
+//**********************************************************************
+//
+// Procedure: CrcSecPlatformInformationPpi
+//
+// Description:
+// Install SecPlatformInformation PPI that Intel Ivybridge CPU reference code needs.
+// (conveys state information out of the SEC phase into PEI)
+//
+// Input:
+// IN EFI_FFS_FILE_HEADER *FfsHeader - pointer to the header of the current firmware file system
+// IN EFI_PEI_SERVICES **PeiServices - pointer to the PeiServices Table
+//
+// Output:
+// EFI_SUCCESS
+//
+// Notes:
+//
+//**********************************************************************
+//<AMI_PHDR_END>
+//PeiInitialize eLink
+
+EFI_STATUS EFIAPI CrcSecPlatformInformationPpi(
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices
+){
+ EFI_STATUS Status;
+
+ // Install the NB Init Policy PPI
+ Status = (*PeiServices)->InstallPpi(PeiServices, &mPeiSecPlatformInformationPpi);
+
+ return EFI_SUCCESS;
+}
+
+
+// VOID
+// SecStartup (
+// IN UINT32 SizeOfRam,
+// IN UINT32 BootFirmwareVolume,
+// IN PEI_MAIN_ENTRY_POINT PeiCoreEntryPoint
+// )
+/*++
+
+Routine Description:
+
+ Entry point to the C language phase of SEC. After the SEC assembly
+ code has initialized some temporary memory and set up the stack,
+ the control is transferred to this function.
+
+Arguments:
+
+ SizeOfRam - Size of the temporary memory available for use.
+ BootFirmwareVolume - Base address of the Boot Firmware Volume.
+ PeiCoreEntryPoint - Pointer to the entry point of the PEI core.
+
+Returns:
+
+ This function never returns
+
+--*/
+// {
+// EFI_PEI_STARTUP_DESCRIPTOR PeiStartup;
+//
+// PeiStartup.SizeOfCacheAsRam = SizeOfRam;
+// PeiStartup.BootFirmwareVolume = BootFirmwareVolume;
+// PeiStartup.DispatchTable = &mPeiSecPlatformInformationPpi;
+//
+// //
+// // Transfer the control to the PEI core
+// //
+// (*PeiCoreEntryPoint) (&PeiStartup);
+//
+// //
+// // Should not come here.
+// //
+// return ;
+// }
diff --git a/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/Flat32.asm b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/Flat32.asm
new file mode 100644
index 0000000..3b973d8
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/Flat32.asm
@@ -0,0 +1,1490 @@
+;
+; This file contains a 'Sample Driver' and is licensed as such
+; under the terms of your license agreement with Intel or your
+; vendor. This file may be modified by the user, subject to
+; the additional terms of the license agreement
+;
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 1999 - 2013, Intel Corporation. All rights reserved.<BR>
+; This software and associated documentation (if any) is furnished
+; under a license and may only be used or copied in accordance
+; with the terms of the license. Except as permitted by such
+; license, no part of this software or documentation may be
+; reproduced, stored in a retrieval system, or transmitted in any
+; form or by any means without the express written consent of
+; Intel Corporation.
+;
+; Module Name:
+;
+; Flat32.asm
+;
+; Abstract:
+;
+; This is the code that goes from real-mode to protected mode.
+; It consumes the reset vector.
+;
+;------------------------------------------------------------------------------
+ INCLUDE Platform.inc
+ INCLUDE Ia32.inc
+ INCLUDE Chipset.inc
+ INCLUDE SecCore.inc
+
+.686p
+.xmm
+.model small, c
+
+EXTRN SecStartup:NEAR
+
+; ECP porting
+EXTRN PcdGet32 (PcdFlashMicrocodeFvBase):DWORD
+EXTRN PcdGet32 (PcdFlashMicrocodeFvSize):DWORD
+EXTRN PcdGet32 (PcdNemCodeCacheSize):DWORD
+EXTRN PcdGet32 (PcdNemCodeCacheBase):DWORD
+EXTRN PcdGet32 (PcdFlashAreaBaseAddress):DWORD
+EXTRN PcdGet32 (PcdTemporaryRamBase):DWORD
+EXTRN PcdGet32 (PcdTemporaryRamSize):DWORD
+EXTRN PcdGet64 (PcdPciExpressBaseAddress):QWORD
+
+_TEXT_REALMODE SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:_TEXT_REALMODE, DS:_TEXT_REALMODE
+
+;------------------------------------------------------------------------------
+;
+; SEC "Security" Code module.
+;
+; Transition to non-paged flat-model protected mode from a
+; hard-coded GDT that provides exactly two descriptors.
+; This is a bare bones transition to protected mode only
+; used for while in PEI and possibly DXE.
+;
+; IA32 specific cache as RAM modules
+;
+; After enabling protected mode, a far jump is executed to
+; TransferToPEI using the newly loaded GDT.
+; This code also enables the Cache-as-RAM
+;
+; RETURNS: none
+;
+; MMX Usage:
+; MM0 = BIST State
+; MM1 = Current Package Physical Info
+; [7:0] = Cluster ID
+; [15:8] = Total Prossor pacakge detected in system
+; [16] = BAD CMOS Flag
+; [17] = AuburnDale or ClarksField
+; [0] = AuburnDale
+; [1] = ClarksField
+; [18] = Contain SEC reset flag
+; CPU Only Reset Flag
+; [19] = Contain SEC reset flag
+; Power Good Reset Flag
+; [23:20] = Reserved
+; [31:24] = Reserved
+; MM2 = store common MAX & MIN ratio
+; MM3 = Patch Revision
+; MM4 = Patch Pointer
+; MM5 = Save time-stamp counter value high32bit
+; MM6 = Save time-stamp counter value low32bit.
+; MM7 = Used in CALL_MMX & RET_ESI micaro
+;
+;------------------------------------------------------------------------------
+
+; Nehalem Reset Boot Flow Start
+
+align 4
+_ModuleEntryPoint PROC NEAR C PUBLIC
+ ;
+ ; Save BIST state in MM0
+ ;
+ fninit ; clear any pending Floating point exceptions
+ movd mm0, eax
+
+ ;
+ ; Save time-stamp counter value
+ ; rdtsc load 64bit time-stamp counter to EDX:EAX
+ ;
+ rdtsc
+ movd mm5, edx
+ movd mm6, eax
+;----------------------------------------------------------------------------------------
+; "Merlin" support
+;----------------------------------------------------------------------------------------
+ xor eax, eax
+ mov es, ax
+ mov ax, cs
+ mov ds, ax
+
+;******************************************************************************
+; BEGIN WARM-START CHANGE
+;******************************************************************************
+;
+; PLATFORM-SPECIFIC EQUATES!
+; These equates define an address which has the following requirements
+; on the target platform:
+; 1. After booting DOS, the memory is not used by other DOS applications
+; or drivers (thus very platform/configuration specific).
+; Minimum of roughly 8 bytes required.
+; 2. The memory contents and address range are not affected by an INIT
+; 3. By default, after booting DOS, the first 4 bytes at this address
+; contain either 0 (cleared memory) or 0xFFFFFFFF.
+; 4. After booting DOS, the memory is writable
+;
+; It's expected that a manual inspection (using ITP) is performed to ensure
+; that the requirements are met. If the manual inspection fails, then a
+; different address must be identified, the below two equates must be
+; changed accordingly, and the platform firmware must be rebuilt.
+; Note that simply changing the platform hardware configuration could
+; break this firmware because drivers may be loaded differently in
+; memory, potentially using the address arbitrarily chosen here.
+;
+ ;
+ ; Check if value in magic address contains non-zero/non-FF value.
+ ; It should actually contain executable code, typically a jmp
+ ; instruction.
+ ;
+ mov ax, MAGIC_SEG
+ mov es, ax
+ mov al, BYTE PTR es:[MAGIC_ADDRESS_IN_SEG]
+
+ ; Check for zero value
+ cmp al, 0EAh ; EA is the FAR JMP opcode that Merlin inserts
+ jz LegacyBiosWarmStart
+
+ ; Check INIT# is asserted by port 0xCF9
+ mov dx, 0CF9h
+ in al, dx
+ cmp al, 04h
+ jnz NotWarmStart
+
+ ;
+ ; Issue hard reset due to client silicon limitations, CPU Only Reset is not supported.
+ ;
+ mov dx, 0CF9h
+ mov al, 06h
+ out dx, al
+
+LegacyBiosWarmStart:
+
+ ;
+ ; Check APIC_BASE_MSR.BIT8 to see if we're the BSP
+ ;
+ mov cx, MSR_APIC_BASE
+ rdmsr
+ test ah, 1
+ jz TightLoop
+ ;
+ ; We're the BSP, so jump to the magic address.
+ ;
+ DB 0EAh
+ DW MAGIC_ADDRESS_IN_SEG
+ DW MAGIC_SEG
+
+ ; Not reached
+NotWarmStart:
+
+;******************************************************************************
+; END WARM-START CHANGE
+;******************************************************************************
+
+ ;
+ ; Enter Protected mode.
+ ;
+ STATUS_CODE (01h) ; BSP_PROTECTED_MODE_START
+ mov esi, OFFSET GdtDesc
+ DB 66h
+ lgdt fword ptr cs:[si]
+ mov eax, cr0 ; Get control register 0
+ or eax, 00000003h ; Set PE bit (bit #0) & MP bit (bit #1)
+ mov cr0, eax ; Activate protected mode
+ mov eax, cr4 ; Get control register 4
+ or eax, 00000600h ; Set OSFXSR bit (bit #9) & OSXMMEXCPT bit (bit #10)
+ mov cr4, eax
+
+ ;
+ ; Now we're in Protected16
+ ; Set up the selectors for protected mode entry
+ ;
+ mov ax, SYS_DATA_SEL
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+
+ ;
+ ; Go to Protected32
+ ;
+ mov esi, offset NemInitLinearAddress
+ jmp fword ptr cs:[si]
+
+TightLoop:
+ cli
+ hlt
+ jmp TightLoop
+
+_ModuleEntryPoint ENDP
+_TEXT_REALMODE ENDS
+
+_TEXT_PROTECTED_MODE SEGMENT PARA PUBLIC USE32 'CODE'
+ ASSUME CS:_TEXT_PROTECTED_MODE, DS:_TEXT_PROTECTED_MODE
+
+CALL_MMX macro RoutineLabel
+
+ local ReturnAddress
+ mov esi, offset ReturnAddress
+ movd mm7, esi ; save ReturnAddress into MM7
+ jmp RoutineLabel
+ReturnAddress:
+
+endm
+
+RET_ESI macro
+
+ movd esi, mm7 ; restore ESP from MM7
+ jmp esi
+
+endm
+
+CALL_EBP macro RoutineLabel
+
+ local ReturnAddress
+ mov ebp, offset ReturnAddress
+ jmp RoutineLabel
+ReturnAddress:
+
+endm
+
+RET_EBP macro
+
+ jmp ebp ; restore ESP from EBP
+
+endm
+
+align 4
+ProtectedModeSECStart PROC NEAR PUBLIC
+
+ STATUS_CODE (02h)
+ CALL_MMX EnableAccessCSR
+
+ STATUS_CODE (03h)
+ CALL_EBP VeryEarlyMicrocodeUpdate
+
+ STATUS_CODE (04h)
+ CALL_MMX DetectNumOfCPUSocket
+
+ STATUS_CODE (05h)
+ CALL_MMX PlatformInitialization
+
+ STATUS_CODE (06h)
+ CALL_MMX InitializeNEM
+
+ STATUS_CODE (07h)
+ CALL_MMX EstablishStack
+
+ STATUS_CODE (08h)
+ jmp CallPeiCoreEntryPoint
+
+ProtectedModeSECStart ENDP
+
+EnableAccessCSR PROC NEAR PRIVATE
+ ;
+ ; get Bus number from CPUID[1] EBX[31:24]
+ ;
+
+ mov eax, 0Bh
+ mov ecx, 1
+ cpuid
+ mov esi, eax
+
+ mov eax, 1 ; bus 0
+ cpuid
+ bswap ebx
+ movzx eax, bl
+ movzx ebx, bl
+ shl eax, BSPApicIDSaveStart ; Save current BSP APIC ID in MM1[31:24]
+ mov cx, si
+ shr bl, cl ; get Bus number in BL
+ or eax, ebx
+ movd mm1, eax ; save Bus number MM1[7:0]
+
+ ;
+ ; Enable MM PCI-E Config Space
+ ; --cr-- use register symbol name; should upper 32 bit be cleared
+ ;
+ mov eax, 080000060h ; MCHBAR
+ mov dx, 0CF8h
+ out dx, eax
+ mov dx, 0CFCh
+ mov eax, 04h
+ out dx, eax
+ in eax, dx
+ or eax, MMCFG_BASE OR ENABLE
+ out dx, eax
+
+ ; Clear reset flag
+ movd eax, mm1
+ and eax, NOT BIT18+BIT19
+ movd mm1, eax
+
+ ;
+ ; Enable SPI prefetching and caching
+ ;
+ mov esi, PCH_LPC_BIOS_CNTL_PCI_ADDR ; Bus0:Dev31:Func0:RegDCh
+ and BYTE PTR es:[esi], NOT (11b SHL 2)
+ or BYTE PTR es:[esi], (10b SHL 2) ; D31:F0:RegDCh[3:2] = 10b
+
+ RET_ESI
+
+EnableAccessCSR ENDP
+
+; STATUS_CODE (03h)
+PlatformInitialization PROC NEAR PRIVATE
+
+ ;
+ ; Program PCI Express base address
+ ;
+
+ mov eax, 80000060h ; 0:0:0:60
+ mov dx, 0CF8h
+ out dx, eax
+ mov dx, 0CFCh
+ ;using Pcd instead
+ ;mov eax, 0e0000000h OR 00h OR 1
+; mov eax, DWORD PTR PcdGet64 (PcdPciExpressBaseAddress)
+ mov eax, DWORD PTR PCIEXPRESS_BASE_ADDRESS
+ or eax, (PCIEX_LENGTH_BIT_SETTING OR 1)
+ out dx, eax
+
+ ;
+ ; Enable Mch Bar
+ ;
+ mov esi, MCHBAR_REG
+ mov eax, (MCH_BASE_ADDRESS + 1)
+ mov Dword Ptr [esi], eax
+
+ ;
+ ; Enable RCRB in PCH.
+ ;
+ mov esi, PCH_LPC_RCRB_PCI_ADDR
+ mov eax, PCH_RCRB_BASE + 1
+ mov Dword Ptr [esi], eax
+
+ ;
+ ; Configure GPIO to be able to initiate LVL change for GPIO48 for S3 resume time calculation.
+ ;
+ ; Enable GPIO BASE I/O registers
+ ;
+ mov eax, PCI_LPC_BASE + 48h
+ mov dx, 0CF8h
+ out dx, eax
+ mov eax, GPIO_BASE_ADDRESS
+ add dx, 4
+ out dx, eax
+
+ mov eax, PCI_LPC_BASE + 4Ch
+ mov dx, 0CF8h
+ out dx, eax
+ add dx, 4
+ in al, dx
+ or al, BIT4 ; GPIOBASE Enable
+ out dx, al
+
+ ;GPIO_USE_SEL2 Register -> 1 = GPIO 0 = Native
+ mov dx, GPIO_BASE_ADDRESS + R_GPIO_USE_SEL2
+ in eax, dx
+ or eax, 010000h ;Enable GPIO48
+ out dx, eax
+
+ ;GP_IO_SEL2 Register -> 1 = Input 0 = Output (if Native Mode don't care)
+ mov dx, GPIO_BASE_ADDRESS + R_GPIO_IO_SEL2
+ in eax, dx
+ and eax, 0FFFEFFFFh ;Configure GPIO48 as Output
+ out dx, eax
+
+ mov dx, GPIO_BASE_ADDRESS + R_GPIO_LVL2
+ in eax, dx
+ or eax, 010000h ;Configure GPIO48 as High
+ out dx, eax
+
+ ;
+ ; Program and Enable ACPI PM Base.
+ ;
+ mov esi, PCH_LPC_PMBASE_PCI_ADDR
+ mov eax, PCH_ACPI_BASE_ADDRESS + 1
+ mov Dword Ptr [esi], eax
+ mov esi, PCH_LPC_ACPICNTL_PCI_ADDR
+ or Dword Ptr [esi], 00000080h
+
+ ;
+ ; PCH BIOS Spec Rev 0.5.0 Section 12.9
+ ; Additional Programming Requirements for USB Support
+ ; Step 2.b
+ ; Clear RCBA + 3598h [0] to 0b
+ ;
+ mov esi, PCH_RCRB_BASE + 3598h
+ mov eax, 0
+ mov Dword Ptr [esi], eax
+
+ ;
+ ; Enable HPET decode in PCH.
+ ;
+ mov esi, PCH_RCRB_BASE + PCH_RCRB_HPET
+ mov eax, PCH_RCRB_HPET_DECODE
+ mov Dword Ptr [esi], eax
+ mov eax, Dword ptr [esi]
+ xor eax, eax
+ mov esi, HPET_COMP_1
+ mov Dword Ptr [esi], eax
+ mov esi, HPET_COMP_2
+ mov Dword ptr [esi], eax
+
+ ;
+ ; Enable the upper 128-byte bank of RTC RAM.
+ ;
+ mov esi, PCH_RCRB_BASE + PCH_RCRB_RTC_CONF
+ mov eax, Dword Ptr [esi]
+ or eax, PCH_RCRB_RTC_CONF_UCMOS_EN
+ mov Dword Ptr [esi], eax
+
+ ;
+ ; Choose Port80 Route
+ ;
+ mov esi, PCH_RCRB_BASE + PCH_RCRB_GCS
+ mov ebx, Dword Ptr [esi]
+ or bl, BIT5
+
+ ;
+ ; check SETUP option - PchPort80Route
+ ; 0 = LPC {Default]; 1 = PCI
+ ;
+; mov al, CMOS_PCH_PORT80_OFFSET ; CMOS Offset = 17h
+; mov dx, RTC_UPPER_INDEX
+; out dx, al
+; inc dx
+; in al, dx
+; test al, BIT0
+; jnz @F
+ and bl, NOT (BIT2) ; Port80h to LPC
+;@@:
+ mov Dword Ptr [esi], ebx
+
+ ;
+ ; Halt TCO Timer
+ ;
+ mov dx, 0468h
+ in ax, dx
+ or ax, BIT11
+ out dx, ax
+
+ ;
+ ; Clear the Second TO status bit
+ ;
+ mov dx, 0466h
+ in ax, dx
+ or ax, BIT1
+ out dx, ax
+
+ RET_ESI
+
+PlatformInitialization ENDP
+
+; STATUS_CODE (03h)
+DetectNumOfCPUSocket PROC NEAR PRIVATE
+
+ ; only one socket
+ movd eax, mm1 ; get MM1 value into EAX
+ mov ah, 01
+ movd mm1, eax ; save CPU pkg count into MM1[15:8]
+
+ RET_ESI
+
+DetectNumOfCPUSocket ENDP
+
+; STATUS_CODE (07h)
+VeryEarlyMicrocodeUpdate PROC NEAR PRIVATE
+
+IF EARLY_MICROCODE_SUPPORT
+ mov ecx, IA32_BIOS_SIGN_ID
+ rdmsr ; CPU PatchID -> EDX
+ cmp edx, 0 ; If microcode has been updated
+ jnz luExit ; Skip if patch already loaded
+
+ mov ecx, IA32_PLATFORM_ID ; To get Platform ID.
+ rdmsr
+ shr edx, 18 ; EDX[0-2] = Platform ID.
+ and dx, 07h ; DX = Platform ID.
+ mov si, dx ; Save Platform ID in FS.
+ mov eax, 01h ; To get CPU signature.
+ cpuid ; EAX = CPU signature.
+ mov cx, si ; CX = Platform ID
+ xor edx, edx
+ bts dx, cx ; EDX = Platform ID bit.
+
+; mov esi, PcdGet32 (PcdFlashMicrocodeFvBase)
+ mov esi, MICROCODE_FV_BASE_ADDRESS
+
+ mov ebx, esi
+ mov bx, FVHEADER_LEN_OFF
+ movzx ebx, WORD PTR [ebx]
+ add esi, ebx
+ add si, FFSHEADER_LEN ; add FFS header
+
+; mov edi, PcdGet32 (PcdFlashMicrocodeFvBase)
+; mov ebx, PcdGet32 (PcdFlashMicrocodeFvSize)
+ mov edi, MICROCODE_FV_BASE_ADDRESS
+ mov ebx, MICROCODE_FV_SIZE
+ add edi, ebx ;End addr of uCodes.
+
+ ; EAX = CPU signature.
+ ; EDX = Platform ID bit.
+ ; ESI = Abs addr of contiguous uCode blocks.
+ ; EDI = Abs addr of contiguous uCode blocks end.
+
+luCheckPatch:
+ cmp (UpdateHeaderStruc PTR ds:[esi]).dProcessorSignature, eax;Sig matched?
+ jnz luCheckUnprogrammed ; No.
+ test (UpdateHeaderStruc PTR ds:[esi]).dProcessorFlags, edx;Platform matched?
+ jnz luFoundMatch ; Yes.
+
+luCheckUnprogrammed:
+ mov ebx, (UpdateHeaderStruc PTR ds:[esi]).dDataSize
+ cmp ebx, 0FFFFFFFFh
+ je luUnprogrammed
+ cmp (UpdateHeaderStruc PTR ds:[esi]).dLoaderRevision, 1
+ je luCheckExtdHdrs
+
+luUnprogrammed:
+ mov ebx, 1024 ; Unprogrammed space, 1KB checks
+ jmp luPoinToNextBlock ; for backword compatibility.
+
+luCheckExtdHdrs:
+ add ebx, SIZEOF(UpdateHeaderStruc)
+ cmp ebx, (UpdateHeaderStruc PTR ds:[esi]).dTotalSize
+ jae luTryNextPatch ; No extd hdrs.
+
+ mov ecx, DWORD PTR ds:[esi + ebx]
+ jcxz luTryNextPatch ; No extd hdrs. (OK to use CX instead of ECX).
+ add ebx, 20 ; Point to the first Extd Sig.
+luNextSig:
+ cmp eax, DWORD PTR ds:[esi + ebx] ;Sig matched?
+ jne lu_00
+ test edx, DWORD PTR ds:[esi + ebx + 4] ;Platform matched?
+ jnz luFoundMatch
+lu_00:
+ add ebx, 12
+ loop luNextSig
+
+luTryNextPatch:
+ mov ebx, (UpdateHeaderStruc PTR ds:[esi]).dTotalSize
+ or ebx, ebx
+ jnz luPoinToNextBlock ; Variable size uCode format.
+ mov ebx, BLOCK_LENGTH_BYTES ; Fixed size uCode format.
+
+;
+; Add alignment check - begin
+;
+ test ebx, 0400h
+ jz @F
+ add ebx, 0400h
+@@:
+;
+; Add alignment check - end
+;
+
+luPoinToNextBlock:
+ add esi, ebx
+ cmp esi, edi
+ jb luCheckPatch ; Check with all patches.
+
+ ; Check possible multiple patch
+ movd eax, mm3
+ movd esi, mm4
+ or eax, eax
+ jnz luLoadPatch
+ jmp luExit ; No matching patch found.
+
+luFoundMatch:
+; MM3 = Patch Revision
+; MM4 = Patch Pointer
+ movd ebx, mm3
+ cmp (UpdateHeaderStruc PTR ds:[esi]).dUpdateRevision, ebx
+ jb luTryNextPatch
+
+ mov ebx, (UpdateHeaderStruc PTR ds:[esi]).dUpdateRevision
+
+luStoreRevPtr:
+ movd mm3, ebx ; save Patch Revision
+ movd mm4, esi ; save Patch Pointer
+ jmp luTryNextPatch
+
+luLoadPatch:
+ mov ecx, IA32_BIOS_UPDT_TRIG
+ mov eax, esi ; EAX - Abs addr of uCode patch.
+ add eax, SIZEOF(UpdateHeaderStruc) ; EAX - Abs addr of uCode data.
+ xor edx, edx ; EDX:EAX - Abs addr of uCode data.
+ wrmsr ; Trigger uCode load.
+
+luExit:
+
+ENDIF
+
+ RET_EBP
+VeryEarlyMicrocodeUpdate ENDP
+
+
+; STATUS_CODE (09h)
+;************************************************************
+; Description:
+;
+; This function initializes the Cache for Data, Stack, and Code
+; as specified in the BIOS Writer's Guide.
+;************************************************************
+InitializeNEM PROC NEAR PRIVATE
+IFDEF BOOT_GUARD_SUPPORT_FLAG
+ ;
+ ; Detect Boot Guard Boot
+ ;
+ mov ecx, MSR_BOOT_GUARD_SACM_INFO ;
+ rdmsr
+ and eax, 01h
+ jnz BootGuardNemSetup
+ENDIF
+
+ ;
+ ; Enable cache for use as stack and for caching code
+ ; The algorithm is specified in the processor BIOS writer's guide
+ ;
+
+ ;
+ ; Ensure that the system is in flat 32 bit protected mode.
+ ;
+ ; Platform Specific - configured earlier
+ ;
+ ; Ensure that only one logical processor in the system is the BSP.
+ ; (Required step for clustered systems).
+ ;
+ ; Platform Specific - configured earlier
+
+ ; Ensure all APs are in the Wait for SIPI state.
+ ; This includes all other logical processors in the same physical processor
+ ; as the BSP and all logical processors in other physical processors.
+ ; If any APs are awake, the BIOS must put them back into the Wait for
+ ; SIPI state by issuing a broadcast INIT IPI to all excluding self.
+ ;
+ mov edi, APIC_ICR_LO ; 0FEE00300h - Send INIT IPI to all excluding self
+ mov eax, ORAllButSelf + ORSelfINIT ; 0000C4500h
+ mov [edi], eax
+
+@@:
+ mov eax, [edi]
+ bt eax, 12 ; Check if send is in progress
+ jc @B ; Loop until idle
+
+ ;
+ ; Load microcode update into BSP.
+ ;
+ ; Ensure that all variable-range MTRR valid flags are clear and
+ ; IA32_MTRR_DEF_TYPE MSR E flag is clear. Note: This is the default state
+ ; after hardware reset.
+ ;
+ ; Platform Specific - MTRR are usually in default state.
+ ;
+
+ ;
+ ; Initialize all fixed-range and variable-range MTRR register fields to 0.
+ ;
+ mov ecx, IA32_MTRR_CAP ; get variable MTRR support
+ rdmsr
+ movzx ebx, al ; EBX = number of variable MTRR pairs
+ shl ebx, 2 ; *4 for Base/Mask pair and WORD size
+ add ebx, MtrrCountFixed * 2 ; EBX = size of Fixed and Variable MTRRs
+
+ xor eax, eax ; Clear the low dword to write
+ xor edx, edx ; Clear the high dword to write
+ ;;;mov ebx, MtrrCount * 2 ; ebx <- sizeof MtrrInitTable
+InitMtrrLoop:
+ add ebx, -2
+ movzx ecx, WORD PTR cs:MtrrInitTable[ebx] ; ecx <- address of mtrr to zero
+ wrmsr
+ jnz InitMtrrLoop ; loop through the whole table
+
+ ;
+ ; Configure the default memory type to un-cacheable (UC) in the
+ ; IA32_MTRR_DEF_TYPE MSR.
+ ;
+ mov ecx, MTRR_DEF_TYPE ; Load the MTRR default type index
+ rdmsr
+ and eax, NOT (00000CFFh) ; Clear the enable bits and def type UC.
+ wrmsr
+
+ ; Configure MTRR_PHYS_MASK_HIGH for proper addressing above 4GB
+ ; based on the physical address size supported for this processor
+ ; This is based on read from CPUID EAX = 080000008h, EAX bits [7:0]
+ ;
+ ; Examples:
+ ; MTRR_PHYS_MASK_HIGH = 00000000Fh For 36 bit addressing
+ ; MTRR_PHYS_MASK_HIGH = 0000000FFh For 40 bit addressing
+ ;
+ mov eax, 80000008h ; Address sizes leaf
+ cpuid
+ sub al, 32
+ movzx eax, al
+ xor esi, esi
+ bts esi, eax
+ dec esi ; esi <- MTRR_PHYS_MASK_HIGH
+
+ ;
+ ; Configure the DataStack region as write-back (WB) cacheable memory type
+ ; using the variable range MTRRs.
+ ;
+
+ ;
+ ; Set the base address of the DataStack cache range
+ ;
+; mov eax, PcdGet32 (PcdTemporaryRamBase)
+ mov eax, TEMPORARY_RAM_BASE_ADDRESS
+ or eax, MTRR_MEMORY_TYPE_WB
+ ; Load the write-back cache value
+ xor edx, edx ; clear upper dword
+ mov ecx, MTRR_PHYS_BASE_0 ; Load the MTRR index
+ wrmsr ; the value in MTRR_PHYS_BASE_0
+
+ ;
+ ; Set the mask for the DataStack cache range
+ ; Compute MTRR mask value: Mask = NOT (Size - 1)
+ ;
+; mov eax, PcdGet32 (PcdTemporaryRamSize)
+ mov eax, TEMPORARY_RAM_SIZE
+ dec eax
+ not eax
+ or eax, MTRR_PHYS_MASK_VALID
+ ; turn on the Valid flag
+ mov edx, esi ; edx <- MTRR_PHYS_MASK_HIGH
+ mov ecx, MTRR_PHYS_MASK_0 ; For proper addressing above 4GB
+ wrmsr ; the value in MTRR_PHYS_BASE_0
+
+ ;
+ ; Configure the BIOS code region as write-protected (WP) cacheable
+ ; memory type using a single variable range MTRR.
+ ;
+ ; Platform Specific - ensure region to cache meets MTRR requirements for
+ ; size and alignment.
+ ;
+
+ ;
+ ; Save MM5 into ESP before program MTRR, because program MTRR will use MM5 as the local variable.
+ ; And, ESP is not initialized before CAR is enabled. So, it is safe ot use ESP here.
+ ;
+ movd esp, mm5
+
+ ;
+ ; Get total size of cache from PCD if it need fix value
+ ;
+; mov eax, PcdGet32 (PcdNemCodeCacheSize)
+ mov eax, CODE_CACHE_SIZE
+ ;
+ ; Calculate NEM size
+ ; Determine LLC size by following RS - Haswell Processor Family BIOS Writer's Guide (BWG) 0.3.0
+ ; Section 4.4.5 - The size of the code region and data region combined must not exceed the size
+ ; of the (Last Level Cache - 0.5MB).
+ ;
+ ; Determine Cache Parameter by CPUID Function 04h
+ ;
+ xor ecx, ecx
+ xor edi, edi
+
+Find_LLC_parameter:
+ mov ecx, edi
+ mov eax, 4
+ cpuid
+ inc edi
+ and eax, 01Fh ; If EAX[4:0]=0, which indicates no more caches, then we can get LLC parameters
+ jnz Find_LLC_parameter
+ ;
+ ; LLC configuration is pointed to edi-2
+ ;
+ dec edi
+ dec edi
+ mov ecx, edi
+ mov eax, 4
+ cpuid
+ ;
+ ; Got LLC parameters
+ ;
+ ; This Cache Size in Bytes = (Ways + 1) * (Partitions + 1) * (Line_Size + 1) * (Sets + 1)
+ ; = (EBX[31:22] + 1) * (EBX[21:12] + 1) * (EBX[11:0] + 1) * (ECX + 1)
+ ;
+ mov eax, ecx
+ inc eax
+ mov edi, ebx
+ shr ebx, 22
+ inc ebx
+ mul ebx
+ mov ebx, edi
+ and ebx, NOT 0FFC00FFFh
+ shr ebx, 12
+ inc ebx
+ mul ebx
+ mov ebx, edi
+ and ebx, 0FFFh
+ inc ebx
+ mul ebx
+ ;
+ ; Maximum NEM size <= (Last Level Cache - 0.5MB)
+ ;
+ sub eax, 512*1024
+Got_NEM_size:
+ ;
+ ; Code cache size = Total NEM size - DataStack size
+ ;
+; sub eax, PcdGet32 (PcdTemporaryRamSize)
+ sub eax, TEMPORARY_RAM_SIZE
+ ;
+ ; Set the base address of the CodeRegion cache range from PCD
+ ; PcdNemCodeCacheBase is set to the offset to flash base,
+ ; so add PcdFlashAreaBaseAddress to get the real code base address.
+ ;
+; mov edi, PcdGet32 (PcdNemCodeCacheBase)
+; add edi, PcdGet32 (PcdFlashAreaBaseAddress)
+ mov edi, CODE_CACHE_BASE_ADDRESS
+ add edi, FLASH_AREA_BASE_ADDRESS
+
+ ;
+ ; Round up to page size
+ ;
+ mov ecx, eax ; Save
+ and ecx, 0FFFF0000h ; Number of pages in 64K
+ and eax, 0FFFFh ; Number of "less-than-page" bytes
+ jz Rounded
+ mov eax, 10000h ; Add the whole page size
+
+Rounded:
+ add eax, ecx ; eax - rounded up code cache size
+
+ ;
+ ; Define "local" vars for this routine
+ ; Note that mm0 is used to store BIST result for BSP,
+ ; mm1 is used to store the number of processor and BSP APIC ID,
+ ; mm6 is used to save time-stamp counter value.
+ ;
+ CODE_SIZE_TO_CACHE TEXTEQU <mm3>
+ CODE_BASE_TO_CACHE TEXTEQU <mm4>
+ NEXT_MTRR_INDEX TEXTEQU <mm5>
+ NEXT_MTRR_SIZE TEXTEQU <mm2>
+ ;
+ ; Initialize "locals"
+ ;
+ sub ecx, ecx
+ movd NEXT_MTRR_INDEX, ecx ; Count from 0 but start from MTRR_PHYS_BASE_1
+
+ ;
+ ; Save remaining size to cache
+ ;
+ movd CODE_SIZE_TO_CACHE, eax ; Size of code cache region that must be cached
+ movd CODE_BASE_TO_CACHE, edi ; Base code cache address
+
+NextMtrr:
+ ;
+ ; Get remaining size to cache
+ ;
+ movd eax, CODE_SIZE_TO_CACHE
+ and eax, eax
+ jz CodeRegionMtrrdone ; If no left size - we are done
+ ;
+ ; Determine next size to cache.
+ ; We start from bottom up. Use the following algorythm:
+ ; 1. Get our own alignment. Max size we can cache equals to our alignment
+ ; 2. Determine what is bigger - alignment or remaining size to cache.
+ ; If aligment is bigger - cache it.
+ ; Adjust remaing size to cache and base address
+ ; Loop to 1.
+ ; If remaining size to cache is bigger
+ ; Determine the biggest 2^N part of it and cache it.
+ ; Adjust remaing size to cache and base address
+ ; Loop to 1.
+ ; 3. End when there is no left size to cache or no left MTRRs
+ ;
+ movd edi, CODE_BASE_TO_CACHE
+ bsf ecx, edi ; Get index of lowest bit set in base address
+ ;
+ ; Convert index into size to be cached by next MTRR
+ ;
+ mov edx, 1h
+ shl edx, cl ; Alignment is in edx
+ cmp edx, eax ; What is bigger, alignment or remaining size?
+ jbe gotSize ; JIf aligment is less
+ ;
+ ; Remaining size is bigger. Get the biggest part of it, 2^N in size
+ ;
+ bsr ecx, eax ; Get index of highest set bit
+ ;
+ ; Convert index into size to be cached by next MTRR
+ ;
+ mov edx, 1
+ shl edx, cl ; Size to cache
+
+GotSize:
+ mov eax, edx
+ movd NEXT_MTRR_SIZE, eax ; Save
+
+ ;
+ ; Compute MTRR mask value: Mask = NOT (Size - 1)
+ ;
+ dec eax ; eax - size to cache less one byte
+ not eax ; eax contains low 32 bits of mask
+ or eax, MTRR_PHYS_MASK_VALID ; Set valid bit
+
+ ;
+ ; Program mask register
+ ;
+ mov ecx, MTRR_PHYS_MASK_1 ; setup variable mtrr
+ movd ebx, NEXT_MTRR_INDEX
+ add ecx, ebx
+
+ mov edx, esi ; edx <- MTRR_PHYS_MASK_HIGH
+ wrmsr
+ ;
+ ; Program base register
+ ;
+ sub edx, edx
+ mov ecx, MTRR_PHYS_BASE_1 ; setup variable mtrr
+ add ecx, ebx ; ebx is still NEXT_MTRR_INDEX
+
+ movd eax, CODE_BASE_TO_CACHE
+ or eax, MTRR_MEMORY_TYPE_WP ; set type to write protect
+ wrmsr
+ ;
+ ; Advance and loop
+ ; Reduce remaining size to cache
+ ;
+ movd ebx, CODE_SIZE_TO_CACHE
+ movd eax, NEXT_MTRR_SIZE
+ sub ebx, eax
+ movd CODE_SIZE_TO_CACHE, ebx
+
+ ;
+ ; Increment MTRR index
+ ;
+ movd ebx, NEXT_MTRR_INDEX
+ add ebx, 2
+ movd NEXT_MTRR_INDEX, ebx
+ ;
+ ; Increment base address to cache
+ ;
+ movd ebx, CODE_BASE_TO_CACHE
+ movd eax, NEXT_MTRR_SIZE
+ add ebx, eax
+ ;
+ ; if carry happens, means NEM base + size over 4G
+ ;
+ jc CodeRegionMtrrdone
+ movd CODE_BASE_TO_CACHE, ebx
+
+ jmp NextMtrr
+
+CodeRegionMtrrdone:
+ ; Program the variable MTRR's MASK register for WDB
+ ; (Write Data Buffer, used in MRC, must be WC type)
+ ;
+ mov ecx, MTRR_PHYS_MASK_1
+ movd ebx, NEXT_MTRR_INDEX
+ add ecx, ebx
+ mov edx, esi ; edx <- MTRR_PHYS_MASK_HIGH
+ mov eax, WDB_REGION_SIZE_MASK OR MTRR_PHYS_MASK_VALID ; turn on the Valid flag
+ wrmsr
+
+ ;
+ ; Program the variable MTRR's BASE register for WDB
+ ;
+ dec ecx
+ xor edx, edx
+ mov eax, WDB_REGION_BASE_ADDRESS OR MTRR_MEMORY_TYPE_WC
+ wrmsr
+
+ ;
+ ; Enable the MTRRs by setting the IA32_MTRR_DEF_TYPE MSR E flag.
+ ;
+ mov ecx, MTRR_DEF_TYPE ; Load the MTRR default type index
+ rdmsr
+ or eax, MTRR_DEF_TYPE_E ; Enable variable range MTRRs
+ wrmsr
+
+ ;
+ ; Enable the logical processor's (BSP) cache: execute INVD and set
+ ; CR0.CD = 0, CR0.NW = 0.
+ ;
+ mov eax, cr0
+ and eax, NOT (CR0_CACHE_DISABLE + CR0_NO_WRITE)
+ invd
+ mov cr0, eax
+ ;
+ ; Enable No-Eviction Mode Setup State by setting
+ ; NO_EVICT_MODE MSR 2E0h bit [0] = '1'.
+ ;
+ mov ecx, NO_EVICT_MODE
+ rdmsr
+ or eax, 1
+ wrmsr
+
+ ;
+ ; Restore MM5 from ESP after program MTRR
+ ;
+ movd mm5, esp
+
+ ;
+ ; One location in each 64-byte cache line of the DataStack region
+ ; must be written to set all cache values to the modified state.
+ ;
+; mov edi, PcdGet32 (PcdTemporaryRamBase)
+; mov ecx, PcdGet32 (PcdTemporaryRamSize)
+ mov edi, TEMPORARY_RAM_BASE_ADDRESS
+ mov ecx, TEMPORARY_RAM_SIZE
+ shr ecx, 6
+ mov eax, CACHE_INIT_VALUE
+@@:
+ mov [edi], eax
+ sfence
+ add edi, 64
+ loopd @b
+
+ ;
+ ; Enable No-Eviction Mode Run State by setting
+ ; NO_EVICT_MODE MSR 2E0h bit [1] = '1'.
+ ;
+ mov ecx, NO_EVICT_MODE
+ rdmsr
+ or eax, 2
+ wrmsr
+
+IFDEF BOOT_GUARD_SUPPORT_FLAG
+ jmp FinishedCacheConfig
+
+ ;
+ ; Jump to here when Boot Guard boot and NEM is initialized by Boot Guard ACM
+ ;
+BootGuardNemSetup:
+ ;
+ ; Finished with cache configuration
+ ;
+ ; Configure MTRR_PHYS_MASK_HIGH for proper addressing above 4GB
+ ; based on the physical address size supported for this processor
+ ; This is based on read from CPUID EAX = 080000008h, EAX bits [7:0]
+ ;
+ ; Examples:
+ ; MTRR_PHYS_MASK_HIGH = 00000000Fh For 36 bit addressing
+ ; MTRR_PHYS_MASK_HIGH = 0000000FFh For 40 bit addressing
+ ;
+ mov eax, 80000008h ; Address sizes leaf
+ cpuid
+ sub al, 32
+ movzx eax, al
+ xor esi, esi
+ bts esi, eax
+ dec esi ; esi <- MTRR_PHYS_MASK_HIGH
+
+ ;
+ ; Configure the DataStack region as write-back (WB) cacheable memory type
+ ; using the variable range MTRRs.
+ ;
+ ;
+ ; Find available MTRR
+ ;
+ CALL_EBP FindFreeMtrr
+
+ ;
+ ; Set the base address of the DataStack cache range
+ ;
+; mov eax, PcdGet32 (PcdTemporaryRamBase)
+ mov eax, TEMPORARY_RAM_BASE_ADDRESS
+ or eax, MTRR_MEMORY_TYPE_WB
+ ; Load the write-back cache value
+ xor edx, edx ; clear upper dword
+ wrmsr ; the value in MTRR_PHYS_BASE_0
+
+ ;
+ ; Set the mask for the DataStack cache range
+ ; Compute MTRR mask value: Mask = NOT (Size - 1)
+ ;
+; mov eax, PcdGet32 (PcdTemporaryRamSize)
+ mov eax, TEMPORARY_RAM_SIZE
+ dec eax
+ not eax
+ or eax, MTRR_PHYS_MASK_VALID
+ ; turn on the Valid flag
+ mov edx, esi ; edx <- MTRR_PHYS_MASK_HIGH
+ inc ecx
+ wrmsr ; the value in MTRR_PHYS_BASE_0
+
+ ;
+ ; Program the variable MTRR's MASK register for WDB
+ ; (Write Data Buffer, used in MRC, must be WC type)
+ ;
+
+ ;
+ ; Find available MTRR
+ ;
+ CALL_EBP FindFreeMtrr
+
+FoundAvailableMtrr:
+ ;
+ ; Program the variable MTRR's BASE register for WDB
+ ;
+ xor edx, edx
+ mov eax, WDB_REGION_BASE_ADDRESS OR MTRR_MEMORY_TYPE_WC
+ wrmsr
+
+ inc ecx
+ mov edx, esi ; edx <- MTRR_PHYS_MASK_HIGH
+ mov eax, WDB_REGION_SIZE_MASK OR MTRR_PHYS_MASK_VALID ; turn on the Valid flag
+ wrmsr
+
+ ;
+ ; One location in each 64-byte cache line of the DataStack region
+ ; must be written to set all cache values to the modified state.
+ ;
+; mov edi, PcdGet32 (PcdTemporaryRamBase)
+; mov ecx, PcdGet32 (PcdTemporaryRamSize)
+ mov edi, TEMPORARY_RAM_BASE_ADDRESS
+ mov ecx, TEMPORARY_RAM_SIZE
+ shr ecx, 6
+ mov eax, CACHE_INIT_VALUE
+@@:
+ mov [edi], eax
+ sfence
+ add edi, 64
+ loopd @b
+ENDIF
+
+ ;
+ ; Finished with cache configuration
+ ;
+FinishedCacheConfig:
+
+ ;
+ ; Optionally Test the Region...
+ ;
+
+ ;
+ ; Test area by writing and reading
+ ;
+ cld
+; mov edi, PcdGet32 (PcdTemporaryRamBase)
+; mov ecx, PcdGet32 (PcdTemporaryRamSize)
+ mov edi, TEMPORARY_RAM_BASE_ADDRESS
+ mov ecx, TEMPORARY_RAM_SIZE
+ shr ecx, 2
+ mov eax, CACHE_TEST_VALUE
+TestDataStackArea:
+ stosd
+ cmp eax, DWORD PTR [edi-4]
+ jnz DataStackTestFail
+ loop TestDataStackArea
+ jmp DataStackTestPass
+
+ ;
+ ; Cache test failed
+ ;
+DataStackTestFail:
+ STATUS_CODE (0D0h)
+ jmp $
+
+ ;
+ ; Configuration test failed
+ ;
+ConfigurationTestFailed:
+ STATUS_CODE (0D1h)
+ jmp $
+
+DataStackTestPass:
+
+ ;
+ ; At this point you may continue normal execution. Typically this would include
+ ; reserving stack, initializing the stack pointer, etc.
+ ;
+
+ ;
+ ; After memory initialization is complete, please follow the algorithm in the BIOS
+ ; Writer's Guide to properly transition to a normal system configuration.
+ ; The algorithm covers the required sequence to properly exit this mode.
+ ;
+
+ RET_ESI
+
+InitializeNEM ENDP
+
+; STATUS_CODE (09h)
+EstablishStack PROC NEAR PRIVATE
+
+ ;
+ ; Enable STACK
+ ;
+ RET_ESI
+
+EstablishStack ENDP
+
+FindFreeMtrr PROC NEAR PRIVATE
+ mov ecx, MTRR_PHYS_MASK_0
+
+@@:
+ rdmsr
+ test eax, 800h
+ jz FoundFreeMtrr
+ add ecx, 2
+ cmp ecx, MTRR_PHYS_MASK_9
+ jbe @b
+ ;
+ ; No available MTRR, halt system
+ ;
+ jmp $
+
+FoundFreeMtrr:
+ dec ecx
+
+ RET_EBP
+
+FindFreeMtrr ENDP
+
+; STATUS_CODE (0Bh)
+CallPeiCoreEntryPoint PROC NEAR PRIVATE
+ ;
+ ; Set stack top pointer
+ ;
+; mov esp, PcdGet32 (PcdTemporaryRamBase)
+; add esp, PcdGet32 (PcdTemporaryRamSize)
+ mov esp, TEMPORARY_RAM_BASE_ADDRESS
+ add esp, TEMPORARY_RAM_SIZE
+
+ ;
+ ; Push CPU count to stack first, then AP's (if there is one)
+ ; BIST status, and then BSP's
+ ;
+
+ ;
+ ; Here work around for BIST
+ ;
+ ; Get number of BSPs
+ movd ecx, mm1
+ movzx ecx, ch
+
+ ; Save number of BSPs
+ push ecx
+
+GetSBSPBist:
+ ; Save SBSP BIST
+ movd eax, mm0
+ push eax
+
+ ; Save SBSP APIC ID
+ movd eax, mm1
+ shr eax, BSPApicIDSaveStart ; Resume APIC ID
+ push eax
+
+ ; Save Time-Stamp Counter
+ movd eax, mm5
+ push eax
+
+ movd eax, mm6
+ push eax
+
+TransferToSecStartup:
+
+
+
+ ; Switch to "C" code
+ STATUS_CODE (0Ch)
+ ;
+ ; Pass entry point of the PEI core
+ ;
+ mov edi, PEI_CORE_ENTRY_BASE ; 0FFFFFFE0h
+ push DWORD PTR ds:[edi]
+
+ ;
+ ; Pass BFV into the PEI Core
+ ;
+ mov edi, FV_MAIN_BASE ; 0FFFFFFFCh
+ push DWORD PTR ds:[edi]
+
+ ; ECPoverride: SecStartup entry point needs 4 parameters
+; push PcdGet32 (PcdTemporaryRamBase)
+ push TEMPORARY_RAM_BASE_ADDRESS
+
+ ;
+ ; Pass stack size into the PEI Core
+ ;
+; push PcdGet32 (PcdTemporaryRamSize)
+ push TEMPORARY_RAM_SIZE
+
+ ;
+ ; Pass Control into the PEI Core
+ ;
+ call SecStartup
+CallPeiCoreEntryPoint ENDP
+
+StartUpAp PROC NEAR
+
+ mov esi, HPET_COMP_2
+ lock inc byte ptr [esi]
+
+ DISABLE_CACHE
+;
+; Halt the AP and wait for the next SIPI
+;
+Ap_Halt:
+ cli
+@@:
+ hlt
+ jmp @B
+ ret
+StartUpAp ENDP
+
+
+CheckValidCMOS PROC NEAR PRIVATE
+ ;
+ ; Check CMOS Status
+ ;
+ mov esi, PCH_LPC_GEN_PMCON_3_ADDR
+ mov eax, es:[esi]
+
+ ; check PWR_FLR and RTC_PWR_STS status
+ and eax, BIT2 + BIT1
+
+ RET_EBP
+CheckValidCMOS ENDP
+
+MtrrInitTable LABEL BYTE
+ DW MTRR_DEF_TYPE
+ DW MTRR_FIX_64K_00000
+ DW MTRR_FIX_16K_80000
+ DW MTRR_FIX_16K_A0000
+ DW MTRR_FIX_4K_C0000
+ DW MTRR_FIX_4K_C8000
+ DW MTRR_FIX_4K_D0000
+ DW MTRR_FIX_4K_D8000
+ DW MTRR_FIX_4K_E0000
+ DW MTRR_FIX_4K_E8000
+ DW MTRR_FIX_4K_F0000
+ DW MTRR_FIX_4K_F8000
+
+MtrrCountFixed EQU (($ - MtrrInitTable) / 2)
+
+ DW MTRR_PHYS_BASE_0
+ DW MTRR_PHYS_MASK_0
+ DW MTRR_PHYS_BASE_1
+ DW MTRR_PHYS_MASK_1
+ DW MTRR_PHYS_BASE_2
+ DW MTRR_PHYS_MASK_2
+ DW MTRR_PHYS_BASE_3
+ DW MTRR_PHYS_MASK_3
+ DW MTRR_PHYS_BASE_4
+ DW MTRR_PHYS_MASK_4
+ DW MTRR_PHYS_BASE_5
+ DW MTRR_PHYS_MASK_5
+ DW MTRR_PHYS_BASE_6
+ DW MTRR_PHYS_MASK_6
+ DW MTRR_PHYS_BASE_7
+ DW MTRR_PHYS_MASK_7
+ DW MTRR_PHYS_BASE_8
+ DW MTRR_PHYS_MASK_8
+ DW MTRR_PHYS_BASE_9
+ DW MTRR_PHYS_MASK_9
+MtrrCount EQU (($ - MtrrInitTable) / 2)
+
+align 10h
+PUBLIC BootGDTtable
+
+;
+; GDT[0]: 0x00: Null entry, never used.
+;
+NULL_SEL EQU $ - GDT_BASE ; Selector [0]
+GDT_BASE:
+BootGDTtable DD 0
+ DD 0
+;
+; Linear data segment descriptor
+;
+LINEAR_SEL EQU $ - GDT_BASE ; Selector [0x8]
+ DW 0FFFFh ; limit 0xFFFFF
+ DW 0 ; base 0
+ DB 0
+ DB 092h ; present, ring 0, data, expand-up, writable
+ DB 0CFh ; page-granular, 32-bit
+ DB 0
+;
+; Linear code segment descriptor
+;
+LINEAR_CODE_SEL EQU $ - GDT_BASE ; Selector [0x10]
+ DW 0FFFFh ; limit 0xFFFFF
+ DW 0 ; base 0
+ DB 0
+ DB 09Bh ; present, ring 0, data, expand-up, not-writable
+ DB 0CFh ; page-granular, 32-bit
+ DB 0
+;
+; System data segment descriptor
+;
+SYS_DATA_SEL EQU $ - GDT_BASE ; Selector [0x18]
+ DW 0FFFFh ; limit 0xFFFFF
+ DW 0 ; base 0
+ DB 0
+ DB 093h ; present, ring 0, data, expand-up, not-writable
+ DB 0CFh ; page-granular, 32-bit
+ DB 0
+
+;
+; System code segment descriptor
+;
+SYS_CODE_SEL EQU $ - GDT_BASE ; Selector [0x20]
+ DW 0FFFFh ; limit 0xFFFFF
+ DW 0 ; base 0
+ DB 0
+ DB 09Ah ; present, ring 0, data, expand-up, writable
+ DB 0CFh ; page-granular, 32-bit
+ DB 0
+;
+; Spare segment descriptor
+;
+SYS16_CODE_SEL EQU $ - GDT_BASE ; Selector [0x28]
+ DW 0FFFFh ; limit 0xFFFFF
+ DW 0 ; base 0
+ DB 0Eh ; Changed from F000 to E000.
+ DB 09Bh ; present, ring 0, code, expand-up, writable
+ DB 00h ; byte-granular, 16-bit
+ DB 0
+;
+; Spare segment descriptor
+;
+SYS16_DATA_SEL EQU $ - GDT_BASE ; Selector [0x30]
+ DW 0FFFFh ; limit 0xFFFF
+ DW 0 ; base 0
+ DB 0
+ DB 093h ; present, ring 0, data, expand-up, not-writable
+ DB 00h ; byte-granular, 16-bit
+ DB 0
+
+;
+; Spare segment descriptor
+;
+SPARE5_SEL EQU $ - GDT_BASE ; Selector [0x38]
+ DW 0 ; limit 0
+ DW 0 ; base 0
+ DB 0
+ DB 0 ; present, ring 0, data, expand-up, writable
+ DB 0 ; page-granular, 32-bit
+ DB 0
+GDT_SIZE EQU $ - BootGDTtable ; Size, in bytes
+
+GdtDesc: ; GDT descriptor
+OffsetGDTDesc EQU $ - _ModuleEntryPoint
+ DW GDT_SIZE - 1 ; GDT limit
+ DD OFFSET BootGDTtable ; GDT base address
+
+NemInitLinearAddress LABEL FWORD
+NemInitLinearOffset LABEL DWORD
+ DD OFFSET ProtectedModeSECStart ; Offset of our 32 bit code
+ DW LINEAR_CODE_SEL
+
+TopOfCar DD TEMPORARY_RAM_BASE_ADDRESS + TEMPORARY_RAM_SIZE
+
+_TEXT_PROTECTED_MODE ENDS
+END
diff --git a/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/Ia32.inc b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/Ia32.inc
new file mode 100644
index 0000000..d799a1e
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/Ia32.inc
@@ -0,0 +1,164 @@
+;@file
+; IA32 architecture MSRs
+;
+;@copyright
+; Copyright (c) 1999 - 2013 Intel Corporation. All rights reserved
+; This software and associated documentation (if any) is furnished
+; under a license and may only be used or copied in accordance
+; with the terms of the license. Except as permitted by such
+; license, no part of this software or documentation may be
+; reproduced, stored in a retrieval system, or transmitted in any
+; form or by any means without the express written consent of
+; Intel Corporation.
+;
+; This file contains a 'Sample Driver' and is licensed as such
+; under the terms of your license agreement with Intel or your
+; vendor. This file may be modified by the user, subject to
+; the additional terms of the license agreement
+;
+
+IA32_MTRR_CAP EQU 0FEh
+MTRR_PHYS_BASE_0 EQU 0200h
+MTRR_PHYS_MASK_0 EQU 0201h
+MTRR_PHYS_BASE_1 EQU 0202h
+MTRR_PHYS_MASK_1 EQU 0203h
+MTRR_PHYS_BASE_2 EQU 0204h
+MTRR_PHYS_MASK_2 EQU 0205h
+MTRR_PHYS_BASE_3 EQU 0206h
+MTRR_PHYS_MASK_3 EQU 0207h
+MTRR_PHYS_BASE_4 EQU 0208h
+MTRR_PHYS_MASK_4 EQU 0209h
+MTRR_PHYS_BASE_5 EQU 020Ah
+MTRR_PHYS_MASK_5 EQU 020Bh
+MTRR_PHYS_BASE_6 EQU 020Ch
+MTRR_PHYS_MASK_6 EQU 020Dh
+MTRR_PHYS_BASE_7 EQU 020Eh
+MTRR_PHYS_MASK_7 EQU 020Fh
+MTRR_PHYS_BASE_8 EQU 0210h
+MTRR_PHYS_MASK_8 EQU 0211h
+MTRR_PHYS_BASE_9 EQU 0212h
+MTRR_PHYS_MASK_9 EQU 0213h
+MTRR_FIX_64K_00000 EQU 0250h
+MTRR_FIX_16K_80000 EQU 0258h
+MTRR_FIX_16K_A0000 EQU 0259h
+MTRR_FIX_4K_C0000 EQU 0268h
+MTRR_FIX_4K_C8000 EQU 0269h
+MTRR_FIX_4K_D0000 EQU 026Ah
+MTRR_FIX_4K_D8000 EQU 026Bh
+MTRR_FIX_4K_E0000 EQU 026Ch
+MTRR_FIX_4K_E8000 EQU 026Dh
+MTRR_FIX_4K_F0000 EQU 026Eh
+MTRR_FIX_4K_F8000 EQU 026Fh
+MTRR_DEF_TYPE EQU 02FFh
+
+MTRR_MEMORY_TYPE_UC EQU 00h
+MTRR_MEMORY_TYPE_WC EQU 01h
+MTRR_MEMORY_TYPE_WT EQU 04h
+MTRR_MEMORY_TYPE_WP EQU 05h
+MTRR_MEMORY_TYPE_WB EQU 06h
+
+MTRR_DEF_TYPE_E EQU 0800h
+MTRR_DEF_TYPE_FE EQU 0400h
+MTRR_PHYSMASK_VALID EQU 0800h
+
+;
+; Define the high 32 bits of MTRR masking
+; This should be read from CPUID EAX = 080000008h, EAX bits [7:0]
+; But for most platforms this will be a fixed supported size so it is
+; fixed to save space.
+;
+MTRR_PHYS_MASK_VALID EQU 0800h
+MTRR_PHYS_MASK_HIGH EQU 00000000Fh ; For 36 bit addressing
+;MTRR_PHYS_MASK_HIGH EQU 0000000FFh ; For 40 bit addressing
+
+IA32_MISC_ENABLE EQU 1A0h
+FAST_STRING_ENABLE_BIT EQU 01h
+
+CR0_CACHE_DISABLE EQU 040000000h
+CR0_NO_WRITE EQU 020000000h
+
+IA32_PLATFORM_ID EQU 017h
+IA32_BIOS_UPDT_TRIG EQU 079h
+IA32_BIOS_SIGN_ID EQU 08Bh
+PLATFORM_INFO EQU 0CEh
+NO_EVICT_MODE EQU 2E0h
+NO_EVICTION_ENABLE_BIT EQU 01h
+
+;
+; MSR definitions
+;
+MSR_IA32_PLATFORM_ID EQU 0017h
+MSR_APIC_BASE EQU 001Bh
+MSR_SOCKET_ID EQU 0039h
+MSR_IA32_FEATURE_CONTROL EQU 003Ah
+MSR_CLOCK_CST_CONFIG_CONTROL EQU 00E2h
+MSR_CLOCK_FLEX_MAX EQU 0194h
+MSR_IA32_PERF_STS EQU 0198h
+MSR_IA32_PERF_CTL EQU 0199h
+MSR_IA32_MISC_ENABLES EQU 01A0h
+MSR_IA32_MC8_MISC2 EQU 0288h
+MSR_IA32_MC7_CTL EQU 041Ch
+MSR_BOOT_GUARD_SACM_INFO EQU 013Ah
+
+;
+; Processor MSR definitions
+;
+MSR_BBL_CR_CTL3 EQU 011Eh ; L2 cache configuration MSR
+B_MSR_BBL_CR_CTL3_L2_NOT_PRESENT EQU 23 ; L2 not present
+B_MSR_BBL_CR_CTL3_L2_ENABLED EQU 8 ; L2 enabled
+B_MSR_BBL_CR_CTL3_L2_HARDWARE_ENABLED EQU 0 ; L2 hardware enabled
+
+P6RatioBitsMask EQU 01Fh ; Bitmask for cpu ratio
+P6_FREQ_LOCKED_BIT EQU 15d
+
+;
+; Local APIC Register Equates
+;
+LOCAL_APIC_ID_REG EQU 0FEE00020h
+APIC_ICR_HI EQU 0FEE00310h
+APIC_ICR_LO EQU 0FEE00300h
+ANDICRMask EQU 0FFF32000h ; AND mask for ICR Saving reserved bits
+ORSelfINIT EQU 000004500h ; OR mask to send INIT IPI to itself
+ORAllButSelf EQU 0000C0000h ; OR mask to set dest field = "All But Self"
+
+;
+; Cache control macro
+;
+DISABLE_CACHE macro
+ mov eax, cr0
+ or eax, CR0_CACHE_DISABLE + CR0_NO_WRITE
+ wbinvd
+ mov cr0, eax
+endm
+
+ENABLE_CACHE macro
+ mov eax, cr0
+ and eax, NOT (CR0_CACHE_DISABLE + CR0_NO_WRITE)
+ wbinvd
+ mov cr0, eax
+endm
+
+VENDOR_ID_REG EQU 0
+PCI_REVISION_ID_REG EQU 8
+CPU_GENERIC_UNCORE_DEV EQU 0
+CPU_GENERIC_UNCORE_FUNC EQU 0
+CPU_LINK_1_DEV EQU 2
+CPU_LINK_1_FUNC EQU 4
+
+B0_CPU_STEPPING EQU 10h
+
+BLOCK_LENGTH_BYTES EQU 2048
+
+UpdateHeaderStruc STRUC
+ dHeaderVersion dd ? ; Header version#
+ dUpdateRevision dd ? ; Update revision#
+ dDate dd ? ; Date in binary (08/13/07 as 0x08132007)
+ dProcessorSignature dd ? ; CPU type, family, model, stepping
+ dChecksum dd ? ; Checksum
+ dLoaderRevision dd ? ; Update loader version#
+ dProcessorFlags dd ? ; Processor Flags
+ dDataSize dd ? ; Size of encrypted data
+ dTotalSize dd ? ; Total size of update in bytes
+ bReserved db 12 dup(?) ; 12 bytes reserved
+UpdateHeaderStruc ENDS
+
diff --git a/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/Platform.inc b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/Platform.inc
new file mode 100644
index 0000000..b49f518
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/Platform.inc
@@ -0,0 +1,196 @@
+;@file
+; Platform Specific Definitions
+;
+;@copyright
+; Copyright (c) 2011 - 2012 Intel Corporation. All rights reserved
+; This software and associated documentation (if any) is furnished
+; under a license and may only be used or copied in accordance
+; with the terms of the license. Except as permitted by such
+; license, no part of this software or documentation may be
+; reproduced, stored in a retrieval system, or transmitted in any
+; form or by any means without the express written consent of
+; Intel Corporation.
+;
+; This file contains an 'Intel Peripheral Driver' and uniquely
+; identified as "Intel Reference Module" and is
+; licensed for Intel CPUs and chipsets under the terms of your
+; license agreement with Intel or your vendor. This file may
+; be modified by the user, subject to additional terms of the
+; license agreement
+;
+
+;(AMI_CHG-)INCLUDE FlashMap.inc
+
+; Set "MINIMUM_BOOT_SUPPORT" flag allows BIOS boot as minimum feature in SEC phase.
+MINIMUM_BOOT_SUPPORT EQU 0 ; ="0", Normal Boot;
+ ; ="1", Minimum Feature Boot
+; "RESET_IN_SEC" flag allows BIOS doing RESET in SEC phase
+RESET_IN_SEC EQU 0 ; ="0", RESET occurs in OemIohInit.c
+ ; ="1", RESET occurs in SEC phase
+
+EARLY_MICROCODE_SUPPORT EQU 1
+DETERMINISTIC_BSP_SUPPORT EQU 0
+DEBUG EQU 1
+
+;
+; IO port to access the upper 128-byte of RTC RAM
+;
+RTC_UPPER_INDEX EQU 072h
+RTC_UPPER_DATA EQU 073h
+
+;
+; Offset of data stored in the upper 128-byte of RTC RAM.
+;
+CMOS_CPU_BSP_SELECT EQU 010h ; BspSelection
+CMOS_CPU_UP_MODE EQU 011h ; UpBootSelection
+
+;
+; Cpu Ratio and Vid stored in the upper 128-byte of RTC RAM.
+;
+CMOS_CPU_RATIO_OFFSET EQU 012h ; ProcessorFlexibleRatio
+CMOS_CPU_CORE_HT_OFFSET EQU 013h ; ProcessorHyperThreadingEnable & EnableCoresInSbsp & EnableCoresInNbsp
+
+;
+; CPU Feature
+;
+CMOS_CPU_BIST_OFFSET EQU 015h ; ProcessorBistEnable
+CMOS_CPU_VMX_OFFSET EQU 016h ; ProcessorVmxEnable
+
+;
+; Port80 Selection
+;
+CMOS_PCH_PORT80_OFFSET EQU 017h ; PchPort80Route
+
+;
+;Flash layout map
+;
+PEICODE_REGION_BASE_ADDRESS EQU FLASH_BASE
+PEICODE_REGION_SIZE EQU FLASH_SIZE
+PEICODE_REGION_SIZE_MASK EQU (NOT (PEICODE_REGION_SIZE - 1))
+
+BIOS_REGION_UPDATABLE_STATUS EQU 0058h ; Offset
+;----------------------------------------------------------------------------------------
+; "Merlin" support used equates
+;----------------------------------------------------------------------------------------
+MAGIC_ADDRESS_IN_SEG EQU 0FFF0h
+MAGIC_SEG EQU 0F000h
+
+;
+; -- Equates for CAR initialization
+; TileSize (must be a power of 2)
+;
+; Define the tile size
+; The tile size and tile placement are critical to ensuring that no data loss occurs
+; See BWG - chapter "Determining Tile Size"
+;
+TILE_SIZE EQU 000000000h
+
+;
+; See BWG - chapter "Determining Cacheable Code Region Base Addresses and Ranges".
+;
+; Now FvRecovery is 6 blocks, so it is seperated into 2 parts to set MTRR:
+; 1. base address = FFFA0000, length = 0x20000
+; 2. base address = FFFC0000, length = 0x40000
+;
+; *** NOTE: If FvRecovery size changes, this code needs to be changed accordingly.
+; Possible enhancement is to dynamically accomodate size changes.
+;
+
+;(AMI_CHG)>
+;-CODE_REGION_BASE_ADDRESS_PART1 EQU FLASH_REGION_FV_RECOVERY_BASE
+;-CODE_REGION_SIZE_PART1 EQU (TILE_SIZE + (128*1024))
+
+MIN_CODE_REGION_SIZE EQU 40000h
+MIN_CODE_REGION_SIZE_MASK EQU (NOT (MIN_CODE_REGION_SIZE - 1))
+CODE_REGION_BASE_ADDRESS_PART1 EQU MKF_CODE_CACHE_BASE_ADDRESS AND 0ffff0000h
+IF MKF_CODE_CACHE_SIZE lt 100000h
+ CODE_REGION_SIZE_PART1 EQU 100000h
+ELSE
+ CODE_REGION_SIZE_PART1 EQU MKF_CODE_CACHE_SIZE
+ENDIF
+
+CODE_REGION_SIZE_MASK_PART1 EQU (NOT (CODE_REGION_SIZE_PART1 - 1))
+
+IF MKF_CODE_CACHE_PART2_BASE
+;-CODE_REGION_BASE_ADDRESS_PART2 EQU CODE_REGION_BASE_ADDRESS_PART1 + CODE_REGION_SIZE_PART1
+;-CODE_REGION_SIZE_PART2 EQU (TILE_SIZE + (256*1024))
+CODE_REGION_BASE_ADDRESS_PART2 EQU MKF_CODE_CACHE_PART2_BASE
+CODE_REGION_SIZE_PART2 EQU MKF_CODE_CACHE_PART2_SIZE
+CODE_REGION_SIZE_MASK_PART2 EQU (NOT (CODE_REGION_SIZE_PART2 - 1))
+ENDIF
+
+IF MKF_WDB_REGION_BASE_ADDRESS
+;-WDB_REGION_BASE_ADDRESS EQU 040000000h
+;-WDB_REGION_SIZE EQU 01000h
+WDB_REGION_BASE_ADDRESS EQU MKF_WDB_REGION_BASE_ADDRESS
+WDB_REGION_SIZE EQU MKF_WDB_REGION_BASE_SIZE
+WDB_REGION_SIZE_MASK EQU (NOT (WDB_REGION_SIZE - 1))
+ENDIF
+;<(AMI_CHG)
+
+;
+; See BWG - chapter "Determining Data Stack Base Address and Range"
+;
+;(AMI_CHG)>
+;-;DATA_STACK_BASE_ADDRESS EQU (CODE_REGION_BASE_ADDRESS - TILE_SIZE - (16*1024 * 1024))
+;-DATA_STACK_BASE_ADDRESS EQU 0FFB00000h
+;-DATA_STACK_SIZE EQU (64*1024) ; 10000h
+DATA_STACK_BASE_ADDRESS EQU MKF_CAR_BASE_ADDRESS
+DATA_STACK_SIZE EQU MKF_CAR_TOTAL_SIZE
+DATA_STACK_SIZE_MASK EQU (NOT (DATA_STACK_SIZE - 1))
+TEMPORARY_RAM_BASE_ADDRESS EQU DATA_STACK_BASE_ADDRESS
+TEMPORARY_RAM_SIZE EQU DATA_STACK_SIZE
+;<(AMI_CHG)
+
+;
+; Cache init and test values
+; These are inverted to flip each bit at least once
+;
+CACHE_INIT_VALUE EQU 0A5A5A5A5h
+CACHE_TEST_VALUE EQU (NOT CACHE_INIT_VALUE)
+
+PEI_CORE_ENTRY_BASE EQU 0FFFFFFE0h
+FV_MAIN_BASE EQU 0FFFFFFFCh
+
+MAX_NR_BUS EQU 0FFh
+MAX_NR_CPU_SOCKETS EQU 2 ; DP example, MP may have 4 or more
+
+;
+; Support EDK1117 build - Sample BASE Address and Size insteads of PcdGet()
+;
+MICROCODE_FV_BASE_ADDRESS EQU 0FFF20000h ; PcdGet32 (PcdFlashMicrocodeFvBase)
+MICROCODE_FV_SIZE EQU 40000h ; PcdGet32 (PcdFlashMicrocodeFvSize)
+CODE_CACHE_BASE_ADDRESS EQU 0FFF80000h ; PcdGet32 (PcdNemCodeCacheBase)
+CODE_CACHE_SIZE EQU 80000h ; PcdGet32 (PcdNemCodeCacheSize)
+FLASH_AREA_BASE_ADDRESS EQU 0FF800000h ; PcdGet32 (PcdFlashAreaBaseAddress)
+;(AMI_CHG)>
+;TEMPORARY_RAM_BASE_ADDRESS EQU 0FEF00000h ; PcdGet32 (PcdTemporaryRamBase)
+;TEMPORARY_RAM_SIZE EQU 2000h ; PcdGet32 (PcdTemporaryRamSize)
+;<(AMI_CHG)
+PCIEXPRESS_BASE_ADDRESS EQU 0E0000000h ; PcdGet64 (PcdPciExpressBaseAddress)
+
+BIT0 EQU 01h
+BIT1 EQU 02h
+BIT2 EQU 04h
+BIT3 EQU 08h
+BIT4 EQU 10h
+BIT5 EQU 20h
+BIT6 EQU 40h
+BIT7 EQU 80h
+BIT8 EQU 100h
+BIT9 EQU 200h
+BIT10 EQU 400h
+BIT11 EQU 800h
+BIT12 EQU 1000h
+BIT13 EQU 2000h
+BIT14 EQU 4000h
+BIT15 EQU 8000h
+BIT16 EQU 10000h
+BIT17 EQU 20000h
+BIT18 EQU 40000h
+BIT19 EQU 80000h
+BIT23 EQU 0800000h
+BIT31 EQU 080000000h
+; Bit definition in MM1
+BadCMOSDetected EQU (BIT0 shl 17)
+BSPApicIDSaveStart EQU 24
diff --git a/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/ResetVec.asm b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/ResetVec.asm
new file mode 100644
index 0000000..54376e5
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/ResetVec.asm
@@ -0,0 +1,108 @@
+;
+; This file contains a 'Sample Driver' and is licensed as such
+; under the terms of your license agreement with Intel or your
+; vendor. This file may be modified by the user, subject to
+; the additional terms of the license agreement
+;
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+; This software and associated documentation (if any) is furnished
+; under a license and may only be used or copied in accordance
+; with the terms of the license. Except as permitted by such
+; license, no part of this software or documentation may be
+; reproduced, stored in a retrieval system, or transmitted in any
+; form or by any means without the express written consent of
+; Intel Corporation.
+
+;
+; Module Name:
+;
+; ResetVec.asm
+;
+; Abstract:
+;
+; Reset Vector Data structure
+; This structure is located at 0xFFFFFFC0
+;
+;------------------------------------------------------------------------------
+
+ .model tiny
+ .686p
+ .stack 0h
+ .code
+
+_TEXT_REALMODE SEGMENT PARA PUBLIC USE16 'CODE'
+ ASSUME CS:_TEXT_REALMODE, DS:_TEXT_REALMODE
+
+ ORG 0h
+;
+; FIT table pointer for LT-SX.
+;
+FitTablePointer DD 0eeeeeeeeh, 0eeeeeeeeh
+
+ ORG 10h
+;
+; This is located at 0xFFFFFFD0h
+;
+ mov di, "AP"
+ jmp ApStartup
+
+ ORG 20h
+;
+; Pointer to the entry point of the PEI core
+; It is located at 0xFFFFFFE0, and is fixed up by some build tool
+; So if the value 8..1 appears in the final FD image, tool failure occurs.
+;
+PeiCoreEntryPoint DD 87654321h
+
+;
+; This is the handler for all kinds of exceptions. Since it's for debugging
+; purpose only, nothing except a deadloop would be done here. Developers could
+; analyze the cause of the exception if a debugger had been attached.
+;
+InterruptHandler PROC
+ jmp $
+ iret
+InterruptHandler ENDP
+
+ ORG 30h
+;
+; For IA32, the reset vector must be at 0xFFFFFFF0, i.e., 4G-16 byte
+; Execution starts here upon power-on/platform-reset.
+;
+ResetHandler:
+ nop
+ nop
+ApStartup:
+ ;
+ ; Jmp Rel16 instruction
+ ; Use machine code directly in case of the assembler optimization
+ ; SEC entry point relatvie address will be fixed up by some build tool.
+ ;
+
+ DB 0e9h
+ DW -3
+
+
+ ORG 38h
+;
+; Ap reset vector segment address is at 0xFFFFFFF8
+; This will be fixed up by some build tool,
+; so if the value 1..8 appears in the final FD image,
+; tool failure occurs
+;
+ApSegAddress dd 12345678h
+
+ ORG 3ch
+;
+; BFV Base is at 0xFFFFFFFC
+; This will be fixed up by some build tool,
+; so if the value 1..8 appears in the final FD image,
+; tool failure occurs.
+;
+BfvBase DD 12345678h
+
+_TEXT_REALMODE ENDS
+
+ END
diff --git a/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/ResetVec.raw b/ReferenceCode/Haswell/SampleCode/SecCore/Sec/Ia32/ResetVec.raw
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;
+}
diff --git a/ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchDxe.c b/ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchDxe.c
new file mode 100644
index 0000000..9c7efae
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchDxe.c
@@ -0,0 +1,631 @@
+/** @file
+
+@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 "TxtOneTouchDxe.h"
+
+TXT_ONE_TOUCH_OP_PROTOCOL mTxtOneTouchOpProtocol = {
+ TxtExecOperation,
+ TxtConfirmationDialog,
+ TxtResetState
+};
+
+EFI_TCG_PROTOCOL *mTcgProtocol;
+TXT_ONE_TOUCH_SETUP mTxtVariable;
+
+/**
+ @param[in] ImageHandle - A handle for this module
+ @param[in] SystemTable - A pointer to the EFI System Table
+
+ @retval EFI_SUCCESS - If TXT initialization succeed
+ @retval EFI_UNLOAD_IMAGE - If TXT criterias are not met
+**/
+EFI_STATUS
+EFIAPI
+DriverEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+
+ Handle = NULL;
+ ZeroMem (&mTxtVariable, sizeof (TXT_ONE_TOUCH_SETUP));
+
+ ///
+ /// Install the protocol
+ ///
+ Status = gBS->InstallProtocolInterface (
+ &Handle,
+ &gTxtOneTouchOpProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mTxtOneTouchOpProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Locate TcgProtocol
+ ///
+ mTcgProtocol = NULL;
+ Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **) &mTcgProtocol);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Initiate the variable if it doesn't exist.
+ ///
+ if (ReadWriteVariable (&mTxtVariable, FALSE) != EFI_SUCCESS) {
+ ReadWriteVariable (&mTxtVariable, TRUE);
+ }
+
+ return Status;
+}
+
+/**
+ Read/Write variable for enable/disable TxT one
+ touch functions
+
+ @param[in] VariableData - Point to Setup variable buffer
+ @param[in] WriteData - TRUE, write changes to Setup Variable. FALSE, not to write variable.
+
+ @retval EFI_SUCCESS - Operation complete successful
+ @retval EFI_INVALID_PARAMETER - VariableData is NULL
+**/
+EFI_STATUS
+ReadWriteVariable (
+ IN OUT TXT_ONE_TOUCH_SETUP *VariableData,
+ IN BOOLEAN WriteData
+ )
+{
+ EFI_STATUS Status;
+ UINTN Size;
+ UINT32 VarAttrib;
+
+ Status = EFI_SUCCESS;
+ Size = 0;
+ VarAttrib = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
+
+ if (VariableData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (WriteData == TRUE) {
+ ///
+ /// Write TxT variable
+ ///
+ Size = sizeof (TXT_ONE_TOUCH_SETUP);
+
+ Status = gRT->SetVariable (
+ TXT_ONE_TOUCH_VAR,
+ &gTxtOneTouchGuid,
+ VarAttrib,
+ Size,
+ VariableData
+ );
+ } else {
+ ///
+ /// Read TxT variable
+ ///
+ Size = sizeof (TXT_ONE_TOUCH_SETUP);
+
+ Status = gRT->GetVariable (
+ TXT_ONE_TOUCH_VAR,
+ &gTxtOneTouchGuid,
+ NULL,
+ &Size,
+ VariableData
+ );
+ }
+
+ return Status;
+}
+
+/**
+ Read TxT Maintenance flag
+
+ @retval TRUE - TxT Maintenance Flag is TRUE
+ @retval FALSE - TxT Maintenance Flag is FALSE
+**/
+BOOLEAN
+CheckTxtMaintenanceFlag (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ ///
+ /// TBD. Need to read TPM NV index 0x50010000
+ ///
+ ///
+ /// Read TxT variable first
+ ///
+ Status = ReadWriteVariable (&mTxtVariable, FALSE);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ return mTxtVariable.NoTxtMaintenance;
+}
+
+/**
+ Extend PPI operation for TxT.
+
+ @param[in] This - Point of TXT_ONE_TOUCH_OP_PROTOCOL
+ @param[in] Command - Operation value for TxT
+
+ @retval EFI_SUCCESS - Execute the Command successful
+ @retval EFI_UNSUPPORTED - Command is not supported
+**/
+EFI_STATUS
+EFIAPI
+TxtExecOperation (
+ IN TXT_ONE_TOUCH_OP_PROTOCOL *This,
+ IN UINT8 Command
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ ///
+ /// Read TxT variable first
+ ///
+ Status = ReadWriteVariable (&mTxtVariable, FALSE);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ ///
+ /// Read variable for TxT One Touch function
+ /// The variable can be Setup variable
+ ///
+ switch (Command) {
+ case DISABLE_DEACTIVATE:
+ ///
+ /// Disable & Deactive TPM
+ /// Disable TxT
+ ///
+ mTxtVariable.TxtEnable = FALSE;
+ break;
+
+ case ENABLE_VT:
+ ///
+ /// Enable VT
+ ///
+ mTxtVariable.VtEnable = TRUE;
+ break;
+
+ case DISABLE_VT_TXT:
+ ///
+ /// Disable VT and TxT
+ ///
+ mTxtVariable.VtEnable = FALSE;
+ mTxtVariable.TxtEnable = FALSE;
+ break;
+
+ case ENABLE_VTD:
+ ///
+ /// Enable VT-d
+ ///
+ mTxtVariable.VtdEnable = TRUE;
+ break;
+
+ case DISABLE_VTD_TXT:
+ ///
+ /// Disable VT-d and TxT
+ ///
+ mTxtVariable.VtdEnable = FALSE;
+ break;
+
+ case ENABLE_ACTTPM_VT_VTD_TXT_DISABLE_STM:
+ ///
+ /// Enable-Active TPM
+ /// Enable VT, VT-d and TxT
+ /// Disable STM
+ ///
+ TpmEnableActive (ENABLE_ACTIVATE);
+ ///
+ /// mTxtVariable.TpmEnable = TRUE;
+ /// mTxtVariable.TpmActive = TRUE;
+ ///
+ mTxtVariable.VtEnable = TRUE;
+ mTxtVariable.VtdEnable = TRUE;
+ mTxtVariable.TxtEnable = TRUE;
+ mTxtVariable.StmEnable = FALSE;
+ break;
+
+ case ENABLE_ACTTPM_VT_VTD_TXT_STM:
+ ///
+ /// Enable-Active TPM
+ /// Enable VT, VT-d, TxT and STM
+ ///
+ TpmEnableActive (ENABLE_ACTIVATE);
+ ///
+ /// mTxtVariable.TpmEnable = TRUE;
+ /// mTxtVariable.TpmActive = TRUE;
+ ///
+ mTxtVariable.VtEnable = TRUE;
+ mTxtVariable.VtdEnable = TRUE;
+ mTxtVariable.TxtEnable = TRUE;
+ mTxtVariable.StmEnable = TRUE;
+ break;
+
+ case DISABLE_STM:
+ ///
+ /// Disable STM
+ ///
+ mTxtVariable.StmEnable = FALSE;
+ break;
+
+ case DISABLE_TXT_STM:
+ ///
+ /// Disable TxT and STM
+ ///
+ mTxtVariable.TxtEnable = FALSE;
+ mTxtVariable.StmEnable = FALSE;
+ break;
+
+ case DISABLE_SENTER_VMX:
+ ///
+ /// Disable SENTER and VMX
+ ///
+ Status = EFI_UNSUPPORTED;
+ break;
+
+ case ENABLE_VMX_SMX_ONLY:
+ ///
+ /// Enable VMX in SMX only
+ ///
+ Status = EFI_UNSUPPORTED;
+ break;
+
+ case ENABLE_VMX_OUTSIDE_SMX:
+ ///
+ /// Enable VMX outside SMX Only
+ ///
+ Status = EFI_UNSUPPORTED;
+ break;
+
+ case ENABLE_VMX:
+ ///
+ /// Enable VMX
+ ///
+ Status = EFI_UNSUPPORTED;
+ break;
+
+ case ENABLE_SENTER_ONLY:
+ ///
+ /// Enable SENTER Only
+ ///
+ Status = EFI_UNSUPPORTED;
+ break;
+
+ case ENABLE_SENTER_VMX_IN_SMX:
+ ///
+ /// Enable SENTER and VMX in SMX
+ ///
+ Status = EFI_UNSUPPORTED;
+ break;
+
+ case ENABLE_SENTER_VMX_OUTSIDE_SMX:
+ ///
+ /// Enable SENTER and VMX outside SMX
+ ///
+ Status = EFI_UNSUPPORTED;
+ break;
+
+ case ENABLE_SENTER_VMX:
+ ///
+ /// Enable SENTER and VMX
+ ///
+ Status = EFI_UNSUPPORTED;
+ break;
+
+ case SET_NO_TXT_MAINTENANCE_FALSE:
+ ///
+ /// Set NoTxtMaintenance Flag FALSE
+ ///
+ mTxtVariable.NoTxtMaintenance = FALSE;
+ break;
+
+ case SET_NO_TXT_MAINTENANCE_TRUE:
+ ///
+ /// Set NoTxtMaintenance Flag TRUE
+ ///
+ mTxtVariable.NoTxtMaintenance = TRUE;
+ break;
+
+ default:
+ return EFI_UNSUPPORTED;
+ }
+ ///
+ /// Validate states
+ ///
+ Status = ValidateTxtStates (&mTxtVariable);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_UNSUPPORTED;
+ } else {
+ ///
+ /// if settings are correct, write it to variable
+ ///
+ Status = ReadWriteVariable (&mTxtVariable, TRUE);
+ }
+
+ return Status;
+}
+
+/**
+ Confirmation dialog for TxT PPI
+
+ @param[in] This - Point of TXT_ONE_TOUCH_OP_PROTOCOL
+ @param[in] Command - Operation value for TxT
+ @param[in] Confirm - User confirm
+
+ @retval EFI_SUCCESS - Execute the Command successful
+ @retval EFI_UNSUPPORTED - Command is not supported
+**/
+EFI_STATUS
+EFIAPI
+TxtConfirmationDialog (
+ IN TXT_ONE_TOUCH_OP_PROTOCOL *This,
+ IN UINT8 Command,
+ IN OUT BOOLEAN *Confirm
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ if (CheckTxtMaintenanceFlag ()) {
+ *Confirm = FALSE;
+ }
+
+ switch (Command) {
+ case DISABLE_DEACTIVATE:
+ ///
+ /// Disable & Deactive TPM
+ /// Disable TxT
+ ///
+ gST->ConOut->OutputString (
+ gST->ConOut,
+ L"\nA configuration change was requested to Disable TxT\n\n\r"
+ );
+
+ break;
+
+ case ENABLE_VT:
+ ///
+ /// Enable VT
+ ///
+ gST->ConOut->OutputString (
+ gST->ConOut,
+ L"\nA configuration change was requested to Enable VT\n\n\r"
+ );
+ break;
+
+ case DISABLE_VT_TXT:
+ ///
+ /// Disable VT and TxT
+ ///
+ gST->ConOut->OutputString (
+ gST->ConOut,
+ L"\nA configuration change was requested to Disable VT and TxT\n\n\r"
+ );
+ break;
+
+ case ENABLE_VTD:
+ ///
+ /// Enable VT-d
+ ///
+ gST->ConOut->OutputString (
+ gST->ConOut,
+ L"\nA configuration change was requested to Enable VT-d\n\n\r"
+ );
+ break;
+
+ case DISABLE_VTD_TXT:
+ ///
+ /// Disable VT-d and TxT
+ ///
+ gST->ConOut->OutputString (
+ gST->ConOut,
+ L"\nA configuration change was requested to Disable VT-d and TxT\n\n\r"
+ );
+ break;
+
+ case ENABLE_ACTTPM_VT_VTD_TXT_DISABLE_STM:
+ ///
+ /// Enable-Active TPM
+ /// Enable VT, VT-d and TxT
+ /// Disable STM
+ ///
+ gST->ConOut->OutputString (
+ gST->ConOut,
+ L"\nA configuration change was requested to Enable/Active TPM and Enable VT/VT-d/TxT, and Disable STM\n\n\r"
+ );
+ break;
+
+ case ENABLE_ACTTPM_VT_VTD_TXT_STM:
+ ///
+ /// Enable-Active TPM
+ /// Enable VT, VT-d, TxT and STM
+ ///
+ gST->ConOut->OutputString (
+ gST->ConOut,
+ L"\nA configuration change was requested to Enable/Active TPM and Enable VT/VT-d/TxT/STM\n\n\r"
+ );
+ break;
+
+ case DISABLE_STM:
+ ///
+ /// Disable STM
+ ///
+ gST->ConOut->OutputString (
+ gST->ConOut,
+ L"\nA configuration change was requested to Disable STM\n\n\r"
+ );
+ break;
+
+ case DISABLE_TXT_STM:
+ ///
+ /// Disable TxT and STM
+ ///
+ gST->ConOut->OutputString (
+ gST->ConOut,
+ L"\nA configuration change was requested to Disable TxT and STM\n\n\r"
+ );
+ break;
+
+ case DISABLE_SENTER_VMX:
+ ///
+ /// Disable SENTER and VMX
+ ///
+ gST->ConOut->OutputString (
+ gST->ConOut,
+ L"\nA configuration change was requested to Disable SENTER and VMX\n\n\r"
+ );
+ break;
+
+ case ENABLE_VMX_SMX_ONLY:
+ ///
+ /// Enable VMX in SMX only
+ ///
+ gST->ConOut->OutputString (
+ gST->ConOut,
+ L"\nA configuration change was requested to Enable VMX in SMX only\n\n\r"
+ );
+ break;
+
+ case ENABLE_VMX_OUTSIDE_SMX:
+ ///
+ /// Enable VMX outside SMX Only
+ ///
+ gST->ConOut->OutputString (
+ gST->ConOut,
+ L"\nA configuration change was requested to Enable VMX outside SMX Only\n\n\r"
+ );
+ break;
+
+ case ENABLE_VMX:
+ ///
+ /// Enable VMX
+ ///
+ gST->ConOut->OutputString (
+ gST->ConOut,
+ L"\nA configuration change was requested to Enable VMX\n\n\r"
+ );
+ break;
+
+ case ENABLE_SENTER_ONLY:
+ ///
+ /// Enable SENTER Only
+ ///
+ gST->ConOut->OutputString (
+ gST->ConOut,
+ L"\nA configuration change was requested to Enable SENTER only\n\n\r"
+ );
+ break;
+
+ case ENABLE_SENTER_VMX_IN_SMX:
+ ///
+ /// Enable SENTER and VMX in SMX
+ ///
+ gST->ConOut->OutputString (
+ gST->ConOut,
+ L"\nA configuration change was requested to Enable SENTER and VMX in SMX\n\n\r"
+ );
+ break;
+
+ case ENABLE_SENTER_VMX_OUTSIDE_SMX:
+ ///
+ /// Enable SENTER and VMX outside SMX
+ ///
+ gST->ConOut->OutputString (
+ gST->ConOut,
+ L"\nA configuration change was requested to Enable SENTER and VMX outside SMX\n\n\r"
+ );
+ break;
+
+ case ENABLE_SENTER_VMX:
+ ///
+ /// Enable SENTER and VMX
+ ///
+ gST->ConOut->OutputString (
+ gST->ConOut,
+ L"\nA configuration change was requested to Enable SENTER and VMX\n\n\r"
+ );
+ break;
+
+ case SET_NO_TXT_MAINTENANCE_FALSE:
+ ///
+ /// Set NoTxtMaintenance Flag FALSE
+ ///
+ gST->ConOut->OutputString (
+ gST->ConOut,
+ L"\nA configuration change was requested to Set TxT Maintenance Flag to FALSE\n\n\r"
+ );
+ break;
+
+ case SET_NO_TXT_MAINTENANCE_TRUE:
+ ///
+ /// Set NoTxtMaintenance Flag TRUE
+ ///
+ gST->ConOut->OutputString (
+ gST->ConOut,
+ L"\nA configuration change was requested to Set TxT Maintenance Flag to TRUE\n\n\r"
+ );
+ break;
+
+ default:
+ return EFI_UNSUPPORTED;
+ }
+
+ return Status;
+}
+
+/**
+ Reset system.
+
+ @param[in] This - Point of TXT_ONE_TOUCH_OP_PROTOCOL
+ @param[in] Command - Operation value for TxT
+
+ @retval EFI_SUCCESS - Always return EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+TxtResetState (
+ IN TXT_ONE_TOUCH_OP_PROTOCOL *This,
+ IN UINT8 Command
+ )
+{
+ EFI_STATUS Status;
+ PCH_RESET_PROTOCOL *PchReset;
+
+ Status = gBS->LocateProtocol (&gPchResetProtocolGuid, NULL, (VOID **) &PchReset);
+ if (!EFI_ERROR (Status)) {
+ PchReset->Reset (PchReset, GlobalReset);
+ } else {
+ gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);
+ }
+
+ ASSERT (FALSE);
+ ///
+ /// Should not be here
+ ///
+ return EFI_SUCCESS;
+}
diff --git a/ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchDxe.cif b/ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchDxe.cif
new file mode 100644
index 0000000..7e4a219
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchDxe.cif
@@ -0,0 +1,14 @@
+<component>
+ name = "TxtOneTouch"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\SampleCode\TxtOneTouch\Dxe"
+ RefName = "TxtOneTouchDxe"
+[files]
+"TxtOneTouchDxe.sdl"
+"TxtOneTouchDxe.dxs"
+"TxtOneTouchDxe.mak"
+"TxtOneTouchDxe.inf"
+"TxtOneTouchDxe.c"
+"TxtOneTouchDxe.h"
+"TxtOneTouchOp.c"
+<endComponent>
diff --git a/ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchDxe.dxs b/ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchDxe.dxs
new file mode 100644
index 0000000..2b37172
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchDxe.dxs
@@ -0,0 +1,42 @@
+/** @file
+ This is the Dependency expression for the TXT Dxe architectural protocol
+
+@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
+
+**/
+
+
+//
+// Common for R8 and R9 codebase
+//
+#include "AutoGen.h"
+#include "DxeDepex.h"
+
+//
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are both "defined" in R8 codebase;
+// BUILD_WITH_EDKII_GLUE_LIB is defined in Edk-Dev-Snapshot-20070228 and later version
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are "not defined" in R9 codebase.
+//
+#if defined (BUILD_WITH_GLUELIB) || defined (BUILD_WITH_EDKII_GLUE_LIB)
+#include "EfiDepex.h"
+#include EFI_PROTOCOL_DEFINITION (CpuPlatformPolicy)
+#include EFI_PROTOCOL_CONSUMER (TcgService)
+#endif
+
+DEPENDENCY_START
+ EFI_TCG_PROTOCOL_GUID AND
+ DXE_CPU_PLATFORM_POLICY_PROTOCOL_GUID
+DEPENDENCY_END
diff --git a/ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchDxe.h b/ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchDxe.h
new file mode 100644
index 0000000..5722d40
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchDxe.h
@@ -0,0 +1,158 @@
+/** @file
+
+@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
+**/
+#ifndef _TXT_ONE_TOUCH_DXE_H_
+#define _TXT_ONE_TOUCH_DXE_H_
+
+///
+/// External include files do NOT need to be explicitly specified in real EDKII
+/// environment
+///
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include EFI_GUID_DEFINITION (TxtOneTouch)
+#include EFI_PROTOCOL_DEFINITION (TxtOneTouchOp)
+#include EFI_PROTOCOL_DEFINITION (PchReset)
+#include EFI_PROTOCOL_CONSUMER (TcgService)
+#endif
+
+#define H2NL(x) (H2NS ((x) >> 16) | (H2NS ((x) & 0xffff) << 16))
+#define H2NS(x) ((((x) << 8) | ((x) >> 8)) & 0xffff)
+#define TPM_PP_USER_ABORT ((TPM_RESULT) (-0x10))
+#define TPM_PP_BIOS_FAILURE ((TPM_RESULT) (-0x0f))
+
+///
+/// TPM PPI Commands
+///
+#define ENABLE 1
+#define ACTIVATE 3
+#define ENABLE_ACTIVATE 6
+#define DISABLE_DEACTIVATE 7
+
+///
+/// Definitions
+///
+#define TXT_ONE_TOUCH_VAR L"TxtOneTouch"
+#pragma pack(push, 1)
+typedef struct {
+ BOOLEAN NoTxtMaintenance;
+ BOOLEAN TpmEnable;
+ BOOLEAN TpmActive;
+ BOOLEAN VtEnable;
+ BOOLEAN VtdEnable;
+ BOOLEAN TxtEnable;
+ BOOLEAN StmEnable;
+ BOOLEAN VmxEnable;
+ BOOLEAN VmxInSmxEnable;
+ BOOLEAN VmxOutsideSmxEnable;
+ BOOLEAN SenterEnable;
+} TXT_ONE_TOUCH_SETUP;
+#pragma pack(pop)
+
+/**
+ Extend PPI operation for TxT.
+
+ @param[in] This - Point of TXT_ONE_TOUCH_OP_PROTOCOL
+ @param[in] Command - Operation value for TxT
+
+ @retval EFI_SUCCESS - Execute the Command successful
+ @retval EFI_UNSUPPORTED - Command is not supported
+**/
+EFI_STATUS
+EFIAPI
+TxtExecOperation (
+ IN TXT_ONE_TOUCH_OP_PROTOCOL *This,
+ IN UINT8 Command
+ );
+
+/**
+ Confirmation dialog for TxT PPI
+
+ @param[in] This - Point of TXT_ONE_TOUCH_OP_PROTOCOL
+ @param[in] Command - Operation value for TxT
+ @param[in] Confirm - User confirm
+
+ @retval EFI_SUCCESS - Execute the Command successful
+ @retval EFI_UNSUPPORTED - Command is not supported
+**/
+EFI_STATUS
+EFIAPI
+TxtConfirmationDialog (
+ IN TXT_ONE_TOUCH_OP_PROTOCOL *This,
+ IN UINT8 Command,
+ IN OUT BOOLEAN *Confirm
+ );
+
+/**
+ Reset system.
+
+ @param[in] This - Point of TXT_ONE_TOUCH_OP_PROTOCOL
+ @param[in] Command - Operation value for TxT
+
+ @retval EFI_SUCCESS - Always return EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+TxtResetState (
+ IN TXT_ONE_TOUCH_OP_PROTOCOL *This,
+ IN UINT8 Command
+ );
+
+/**
+ Enable/Active TPM
+
+ @param[in] Command - The operation code for TxT One Touch function
+
+ @retval EFI_SUCCESS - TPM command lunch success
+ @retval EFI_UNSUPPORTED - The Command is not supported
+ @retval EFI_DEVICE_ERROR - Faile to lunch TPM command
+**/
+EFI_STATUS
+TpmEnableActive (
+ IN UINT8 Command
+ );
+
+/**
+ Read/Write variable for enable/disable TxT one
+ touch functions
+
+ @param[in] VariableData - Point to Setup variable buffer
+ @param[in] WriteData - TRUE, write changes to Setup Variable. FALSE, not to write variable.
+
+ @retval EFI_SUCCESS - Operation complete successful
+ @retval EFI_INVALID_PARAMETER - VariableData is NULL
+**/
+EFI_STATUS
+ReadWriteVariable (
+ IN OUT TXT_ONE_TOUCH_SETUP *VariableData,
+ IN BOOLEAN WriteData
+ );
+
+/**
+ Verify the status of Chipset capaibility and Setup settings
+
+ @param[in] Data - Point to TXT_ONE_TOUCH_SETUP
+
+ @exception EFI_UNSUPPORTED - The system is not able to lunch TxT
+ @retval EFI_SUCCESS - The system is able to lunch TxT
+**/
+EFI_STATUS
+ValidateTxtStates (
+ IN TXT_ONE_TOUCH_SETUP *Data
+ );
+
+#endif
diff --git a/ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchDxe.inf b/ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchDxe.inf
new file mode 100644
index 0000000..5a7038b
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchDxe.inf
@@ -0,0 +1,113 @@
+## @file
+# Component description file for TXTDXE module
+#
+#@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
+#
+
+[defines]
+BASE_NAME = TxtOneTouchDxe
+FILE_GUID = 67791e00-0c05-4ae7-a921-fc4057221653
+COMPONENT_TYPE = BS_DRIVER
+
+[sources.common]
+ TxtOneTouchDxe.c
+ TxtOneTouchOp.c
+ TxtOneTouchDxe.h
+
+#
+# Edk II Glue Driver Entry Point
+#
+ EdkIIGlueDxeDriverEntryPoint.c
+
+[includes.common]
+ .
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Framework/Protocol
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Sample/Include
+ $(EDK_SOURCE)/Foundation/Cpu/Pentium/Include
+
+#
+# Edk II Glue Library, some hearder are included by R9 header so have to include
+#
+
+ $(EFI_SOURCE)
+ $(EFI_SOURCE)/Framework
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+#
+# Typically the sample code referenced will be available in the code base already
+# So keep this include at the end to defer to the source base definition
+# and only use the sample code definition if source base does not include these files.
+#
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/SampleCode
+
+[libraries.common]
+ EfiGuidLib
+ EdkFrameworkProtocolLib
+ EdkProtocolLib
+ EfiScriptLib
+ CpuGuidLib
+ CpuProtocolLib
+ $(PROJECT_PCH_FAMILY)ProtocolLib
+ EdkIIGlueBaseLib
+ EdkIIGlueBaseMemoryLib
+ EdkIIGlueDxeReportStatusCodeLib
+ EdkIIGlueDxeServicesTableLib
+ EdkIIGlueDxeDebugLibReportStatusCode
+ EdkIIGlueUefiBootServicesTableLib
+ EdkIIGlueUefiRuntimeServicesTableLib
+ EdkIIGlueUefiLib
+ EdkIIGlueDxeHobLib
+#
+# Typically the sample code referenced will be available in the code base already
+# So keep this include at the end to defer to the source base definition
+# and only use the sample code definition if source base does not include these files.
+#
+ CpuSampleProtocolLib
+
+[nmake.common]
+ IMAGE_ENTRY_POINT = _ModuleEntryPoint
+ DPX_SOURCE = TxtOneTouchDxe.dxs
+#
+# Module Entry Point
+#
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=DriverEntry
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_BASE_LIB__ \
+ -D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ -D __EDKII_GLUE_DXE_REPORT_STATUS_CODE_LIB__ \
+ -D __EDKII_GLUE_DXE_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ -D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_UEFI_LIB__ \
+ -D __EDKII_GLUE_DXE_HOB_LIB__
diff --git a/ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchDxe.mak b/ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchDxe.mak
new file mode 100644
index 0000000..7481ab7
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchDxe.mak
@@ -0,0 +1,88 @@
+#/*++
+#Copyright (c) 2009 - 2011 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:
+#
+# TxtPolicyInitDxeLib.mak
+#
+#Abstract:
+#
+# Make file for the TxtPolicyInitDxeLib component
+#
+#--*/
+all : TxtOneTouchDxe
+
+TxtOneTouchDxe : $(BUILD_DIR)\TxtOneTouchDxe.mak TxtOneTouchDxeBin
+
+$(BUILD_DIR)\TxtOneTouchDxe.mak : $(TxtOneTouchDxe_DIR)\$(@B).cif $(TxtOneTouchDxe_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(TxtOneTouchDxe_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+TxtOneTouchDxeIncludes=\
+ $(MISCFRAMEWORK_INCLUDES)\
+ $(EdkIIGlueLib_INCLUDES)\
+ /I$(INTEL_PCH_DIR)\
+ $(PROJECT_CPU_INCLUDES)\
+ $(TXT_INCLUDES)\
+
+TxtOneTouchDxeDefines=\
+ $(MY_DEFINES)\
+ /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=DriverEntry"\
+ /D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ /D __EDKII_GLUE_BASE_LIB__ \
+ /D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ /D __EDKII_GLUE_DXE_REPORT_STATUS_CODE_LIB__ \
+ /D __EDKII_GLUE_DXE_SERVICES_TABLE_LIB__ \
+ /D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ /D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \
+ /D __EDKII_GLUE_UEFI_LIB__ \
+ /D __EDKII_GLUE_UEFI_DEVICE_PATH_LIB__ \
+ /D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ \
+ /D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \
+ /D __EDKII_GLUE_DXE_HOB_LIB__ \
+
+TxtOneTouchDxeLibs=\
+ $(EFIGUIDLIB)\
+ $(EDKFRAMEWORKPROTOCOLLIB)\
+ $(EDKPROTOCOLLIB)\
+ $(EdkIIGlueBaseIoLibIntrinsic_LIB)\
+ $(EdkIIGlueBaseLib_LIB)\
+ $(EdkIIGlueBaseMemoryLib_LIB)\
+ $(EdkIIGlueDxeReportStatusCodeLib_LIB)\
+ $(EdkIIGlueDxeServicesTableLib_LIB)\
+ $(EdkIIGlueDxeDebugLibReportStatusCode_LIB)\
+ $(EdkIIGlueUefiBootServicesTableLib_LIB)\
+ $(EdkIIGlueUefiLib_LIB)\
+ $(EdkIIGlueBasePciLibPciExpress_LIB)\
+ $(EdkIIGlueDxeMemoryAllocationLib_LIB)\
+ $(EdkIIGlueBaseTimerLibLocalApic_LIB)\
+ $(EdkIIGlueDxeHobLib_LIB)\
+ $(EdkIIGlueHiiLib_LIB)\
+ $(EFIDRIVERLIB)\
+ $(UEFIEFIIFRSUPPORTLIB)\
+ $(EFISCRIPTLIB)\
+ $(CpuProtocolLib_LIB)\
+ $(CpuGuidLib_LIB)\
+ $(CPUIA32LIB)\
+ $(CpuSampleCodeProtocolLib_LIB)\
+ $(INTEL_PCH_PROTOCOL_LIB)
+
+TxtOneTouchDxeBin : $(TxtOneTouchDxeLibs)
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\TxtOneTouchDxe.mak all\
+ "MY_INCLUDES=$(TxtOneTouchDxeIncludes)"\
+ "MY_DEFINES=$(TxtOneTouchDxeDefines)"\
+ "GUID=67791e00-0c05-4ae7-a921-fc4057221653"\
+ "AFLAGS=$(AFLAGS) $(TxtOneTouchDxeIncludes)"\
+ ENTRY_POINT=_ModuleEntryPoint \
+ TYPE=BS_DRIVER \
+ EDKIIModule=DXEDRIVER\
+ DEPEX1=$(TxtOneTouchDxe_DIR)\TxtOneTouchDxe.dxs\
+ DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX\
+ COMPRESS=1\
diff --git a/ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchDxe.sdl b/ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchDxe.sdl
new file mode 100644
index 0000000..541ccf4
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchDxe.sdl
@@ -0,0 +1,28 @@
+TOKEN
+ Name = "TxtOneTouchSupport"
+ Value = "1"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+ Help = "Main switch"
+End
+
+MODULE
+ Help = "Includes TxtOneTouchDxe.mak into project"
+ File = "TxtOneTouchDxe.mak"
+End
+
+PATH
+ Name = "TxtOneTouchDxe_DIR"
+ Help = "TxT DXE Policy Init directory"
+End
+
+
+ELINK
+ Name = "$(BUILD_DIR)\TxtOneTouchDxe.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End
+
diff --git a/ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchOp.c b/ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchOp.c
new file mode 100644
index 0000000..860e90d
--- /dev/null
+++ b/ReferenceCode/Haswell/SampleCode/TxtOneTouch/Dxe/TxtOneTouchOp.c
@@ -0,0 +1,178 @@
+/** @file
+
+@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 "TxtOneTouchDxe.h"
+#include "Tpm12.h"
+#include "CpuIa32.h"
+
+extern EFI_TCG_PROTOCOL *mTcgProtocol;
+
+/**
+ Execute TPM command
+
+ @param[in] TcgProtocol - Point to EFI_TCG_PROTOCOL
+ @param[in] Ordinal - TPM Command code
+ @param[in] AdditionalParameterSize - Size of additional parameters
+ @param[in] AdditionalParameters - Point to the buffer saves additional parameters
+
+ @retval EFI_SUCCESS - TPM command lunch success
+ @retval TPM_PP_BIOS_FAILURE - BIOS fail to execute TPM command
+**/
+TPM_RESULT
+TpmCommandNoReturnData (
+ IN EFI_TCG_PROTOCOL *TcgProtocol,
+ IN TPM_COMMAND_CODE Ordinal,
+ IN UINTN AdditionalParameterSize,
+ IN VOID *AdditionalParameters
+ )
+{
+ EFI_STATUS Status;
+ TPM_RQU_COMMAND_HDR *TpmRqu;
+ TPM_RSP_COMMAND_HDR TpmRsp;
+ UINT32 Size;
+
+ TpmRqu = (TPM_RQU_COMMAND_HDR *) AllocatePool (sizeof (*TpmRqu) + AdditionalParameterSize);
+ if (TpmRqu == NULL) {
+ return TPM_PP_BIOS_FAILURE;
+ }
+
+ TpmRqu->tag = H2NS (TPM_TAG_RQU_COMMAND);
+ Size = (UINT32) (sizeof (*TpmRqu) + AdditionalParameterSize);
+ TpmRqu->paramSize = H2NL (Size);
+ TpmRqu->ordinal = H2NL (Ordinal);
+ CopyMem (TpmRqu + 1, AdditionalParameters, AdditionalParameterSize);
+
+ Status = TcgProtocol->PassThroughToTpm (
+ TcgProtocol,
+ Size,
+ (UINT8 *) TpmRqu,
+ (UINT32) sizeof (TpmRsp),
+ (UINT8 *) &TpmRsp
+ );
+ FreePool (TpmRqu);
+ if (EFI_ERROR (Status) || (TpmRsp.tag != H2NS (TPM_TAG_RSP_COMMAND))) {
+ return TPM_PP_BIOS_FAILURE;
+ }
+
+ return H2NL (TpmRsp.returnCode);
+}
+
+/**
+ Enable/Active TPM
+
+ @param[in] Command - The operation code for TxT One Touch function
+
+ @retval EFI_SUCCESS - TPM command lunch success
+ @retval EFI_UNSUPPORTED - The Command is not supported
+ @retval EFI_DEVICE_ERROR - Faile to lunch TPM command
+**/
+EFI_STATUS
+TpmEnableActive (
+ IN UINT8 Command
+ )
+{
+ TPM_RESULT TpmResponse;
+ EFI_STATUS Status;
+ BOOLEAN BoolVal;
+
+ BoolVal = FALSE;
+ TpmResponse = 0;
+ Status = EFI_SUCCESS;
+
+ switch (Command) {
+ case ENABLE:
+ TpmResponse = TpmCommandNoReturnData (
+ mTcgProtocol,
+ TPM_ORD_PhysicalEnable,
+ 0,
+ NULL
+ );
+ break;
+
+ case ACTIVATE:
+ BoolVal = FALSE;
+ TpmResponse = TpmCommandNoReturnData (
+ mTcgProtocol,
+ TPM_ORD_PhysicalSetDeactivated,
+ sizeof (BoolVal),
+ &BoolVal
+ );
+ break;
+
+ case ENABLE_ACTIVATE:
+ Status = TpmEnableActive (ENABLE);
+ if (Status == EFI_SUCCESS) {
+ Status = TpmEnableActive (ACTIVATE);
+ }
+
+ return Status;
+
+ default:
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+
+ if (TpmResponse != 0) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ return Status;
+}
+
+/**
+ Verify the status of Chipset capaibility and Setup settings
+
+ @param[in] Data - Point to TXT_ONE_TOUCH_SETUP
+
+ @exception EFI_UNSUPPORTED - The system is not able to lunch TxT
+ @retval EFI_SUCCESS - The system is able to lunch TxT
+**/
+EFI_STATUS
+ValidateTxtStates (
+ IN TXT_ONE_TOUCH_SETUP *Data
+ )
+{
+ EFI_CPUID_REGISTER CpuidRegs;
+
+ AsmCpuid (
+ 1,
+ &CpuidRegs.RegEax,
+ &CpuidRegs.RegEbx,
+ &CpuidRegs.RegEcx,
+ &CpuidRegs.RegEdx
+ );
+
+ if (Data->VtEnable) {
+ ///
+ /// Check if VMX supported
+ ///
+ if ((CpuidRegs.RegEcx & 0x020) == 0) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ if (Data->TxtEnable) {
+ ///
+ /// Check if TxT & VMX supported
+ ///
+ if ((CpuidRegs.RegEcx & 0x060) == 0) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/ReferenceCode/Haswell/Txt/BiosAcm/HSW_BIOSAC_DBG_Rev1_5.BIN b/ReferenceCode/Haswell/Txt/BiosAcm/HSW_BIOSAC_DBG_Rev1_5.BIN
new file mode 100644
index 0000000..01478dc
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/BiosAcm/HSW_BIOSAC_DBG_Rev1_5.BIN
Binary files differ
diff --git a/ReferenceCode/Haswell/Txt/BiosAcm/HSW_BIOSAC_PRO_NPW_Rev1_5.BIN b/ReferenceCode/Haswell/Txt/BiosAcm/HSW_BIOSAC_PRO_NPW_Rev1_5.BIN
new file mode 100644
index 0000000..04461da
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/BiosAcm/HSW_BIOSAC_PRO_NPW_Rev1_5.BIN
Binary files differ
diff --git a/ReferenceCode/Haswell/Txt/BiosAcm/HSW_BIOSAC_PRO_Rev1_5.BIN b/ReferenceCode/Haswell/Txt/BiosAcm/HSW_BIOSAC_PRO_Rev1_5.BIN
new file mode 100644
index 0000000..9ac1a89
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/BiosAcm/HSW_BIOSAC_PRO_Rev1_5.BIN
Binary files differ
diff --git a/ReferenceCode/Haswell/Txt/BiosAcm/TxtBiosAcm.cif b/ReferenceCode/Haswell/Txt/BiosAcm/TxtBiosAcm.cif
new file mode 100644
index 0000000..1ccd13b
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/BiosAcm/TxtBiosAcm.cif
@@ -0,0 +1,14 @@
+<component>
+ name = "TxtBiosAcm"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\Txt\BiosAcm"
+ RefName = "TxtBiosAcm"
+[files]
+"TxtBiosAcm.sdl"
+"TxtBiosAcm.mak"
+"HSW_BIOSAC_DBG_Rev1_5.BIN"
+"HSW_BIOSAC_PRO_Rev1_5.BIN"
+"HSW_BIOSAC_PRO_NPW_Rev1_5.BIN"
+"TxtBiosAcm.inf"
+"makefile.new"
+<endComponent>
diff --git a/ReferenceCode/Haswell/Txt/BiosAcm/TxtBiosAcm.inf b/ReferenceCode/Haswell/Txt/BiosAcm/TxtBiosAcm.inf
new file mode 100644
index 0000000..93e53da
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/BiosAcm/TxtBiosAcm.inf
@@ -0,0 +1,33 @@
+## @file
+# Component description file for Biosac module
+#
+#@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
+#
+
+
+[defines]
+BASE_NAME = BiosAc
+FILE_GUID = 2d27c618-7dcd-41f5-bb10-21166be7e143
+COMPONENT_TYPE = FILE
+BUILD_TYPE = MAKEFILE
+
+[sources.common]
+
+[includes.common]
+
+[libraries.common]
+
+[nmake.common]
diff --git a/ReferenceCode/Haswell/Txt/BiosAcm/TxtBiosAcm.mak b/ReferenceCode/Haswell/Txt/BiosAcm/TxtBiosAcm.mak
new file mode 100644
index 0000000..e88a6d0
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/BiosAcm/TxtBiosAcm.mak
@@ -0,0 +1,13 @@
+# MAK file for the ModulePart:TxtBiosAcm binary
+all: $(BUILD_DIR)\BiosAcm.ffs $(TxtBiosAcm_DIR)\TxtBiosAcm.mak
+
+$(BUILD_DIR)\HSW_BIOSAC.bin :
+ COPY $(TxtBiosAcmFile) $(BUILD_DIR)\HSW_BIOSAC.bin $(SILENT_OUT)
+
+$(BUILD_DIR)\BiosAcm.ffs : $(BUILD_DIR)\HSW_BIOSAC.bin
+ $(MAKE) /f Core\FFS.mak \
+ BUILD_DIR=$(BUILD_DIR) \
+ GUID=2d27c618-7dcd-41f5-bb10-21166be7e143\
+ TYPE=EFI_FV_FILETYPE_RAW \
+ FFS_ALIGNMENT=5 FFS_CHECKSUM=0\
+ RAWFILE=$(BUILD_DIR)\HSW_BIOSAC.bin FFSFILE=$(BUILD_DIR)\BiosAcm.ffs COMPRESS=0 NAME=BiosAcm \ No newline at end of file
diff --git a/ReferenceCode/Haswell/Txt/BiosAcm/TxtBiosAcm.sdl b/ReferenceCode/Haswell/Txt/BiosAcm/TxtBiosAcm.sdl
new file mode 100644
index 0000000..a8d7700
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/BiosAcm/TxtBiosAcm.sdl
@@ -0,0 +1,39 @@
+TOKEN
+ Name = "TxtBiosAcm_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable TxtBiosAcm support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+End
+
+TOKEN
+ Name = "TxtBiosAcmFile"
+ Value = "ReferenceCode\Haswell\Txt\BiosAcm\HSW_BIOSAC_PRO_Rev1_5.BIN"
+ TokenType = File
+ TargetMAK = Yes
+End
+
+PATH
+ Name = "TxtBiosAcm_DIR"
+ Help = "TXT BIOS ACM directory"
+End
+
+MODULE
+ Help = "Includes TxtBiosAcm.mak to Project"
+ File = "TxtBiosAcm.mak"
+End
+
+ELINK
+ Name = "/I$(TxtBiosAcm_DIR)"
+ Parent = "TXT_INCLUDES"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\BiosAcm.ffs"
+ Parent = "FV_BB"
+ InvokeOrder = AfterParent
+End
+
diff --git a/ReferenceCode/Haswell/Txt/BiosAcm/makefile.new b/ReferenceCode/Haswell/Txt/BiosAcm/makefile.new
new file mode 100644
index 0000000..47222aa
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/BiosAcm/makefile.new
@@ -0,0 +1,63 @@
+#++
+# 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 - 2011 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:
+#
+# makefile.new
+#
+# Abstract:
+#
+# makefile for Biosac.bin file
+#
+#--
+
+
+#
+# Globals
+#
+BIN_DIR = $(BUILD_DIR)\$(PROCESSOR)
+TOOLCHAIN = TOOLCHAIN_$(PROCESSOR)
+
+TOOLBIN_DIR = $(BUILD_DIR)\Tools
+
+#
+# Include CommonTools.env enviroment
+#
+
+!INCLUDE $(BUILD_DIR)\PlatformTools.env
+
+BIOSAC_GUID = 2d27c618-7dcd-41f5-bb10-21166be7e143
+
+
+all :
+ copy $(SOURCE_DIR)\BiosAc.bin $(BIN_DIR)\BiosAc.bin
+
+ $(GENFFSFILE) -B $(BIN_DIR) -V -P1 <<$(BIN_DIR)\BiosAc.pkg
+PACKAGE.INF
+[.]
+BASE_NAME = BiosAc
+FFS_FILEGUID = $(BIOSAC_GUID)
+FFS_FILETYPE = EFI_FV_FILETYPE_RAW
+FFS_ATTRIB_CHECKSUM = FALSE
+FFS_ALIGNMENT = 5
+
+IMAGE_SCRIPT =
+{
+ BiosAc.bin
+}
+<<KEEP
+
diff --git a/ReferenceCode/Haswell/Txt/Tools/Apfixup.txt b/ReferenceCode/Haswell/Txt/Tools/Apfixup.txt
new file mode 100644
index 0000000..b4e2c01
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/Tools/Apfixup.txt
@@ -0,0 +1,33 @@
+#/*++
+# 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 - 2011 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.
+#form or by any means without the express written consent of
+#Intel Corporation.
+#
+#
+# Module Name:
+#
+# Apfixup.txt
+#
+# Abstract:
+#
+# File format:
+#-----------------
+# Offset, Width
+#
+
+0x12, 4
diff --git a/ReferenceCode/Haswell/Txt/Tools/Stafixup.exe b/ReferenceCode/Haswell/Txt/Tools/Stafixup.exe
new file mode 100644
index 0000000..6a646b4
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/Tools/Stafixup.exe
Binary files differ
diff --git a/ReferenceCode/Haswell/Txt/Tools/TxtTools.cif b/ReferenceCode/Haswell/Txt/Tools/TxtTools.cif
new file mode 100644
index 0000000..db90d14
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/Tools/TxtTools.cif
@@ -0,0 +1,10 @@
+<component>
+ name = "TxtTools"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\Txt\Tools"
+ RefName = "TxtTools"
+[files]
+"Apfixup.txt"
+"Stafixup.exe"
+"TxtTools.sdl"
+<endComponent>
diff --git a/ReferenceCode/Haswell/Txt/Tools/TxtTools.sdl b/ReferenceCode/Haswell/Txt/Tools/TxtTools.sdl
new file mode 100644
index 0000000..7dd99ed
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/Tools/TxtTools.sdl
@@ -0,0 +1,23 @@
+TOKEN
+ Name = "TxtTools_SUPPORT"
+ Value = "1"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+ Help = "Main switch to enable TxtTools support in Project"
+End
+
+PATH
+ Name = "TxtTools_DIR"
+ Help = "TXT Tools directory"
+End
+
+TOKEN
+ Name = "AP_FIXUP_FILE"
+ Value = "$(TxtTools_DIR)\Apfixup.txt"
+ Help = "Name of AP FFS fixup table file."
+ TokenType = Expression
+ TargetMAK = Yes
+ TargetH = Yes
+End
diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.c b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.c
new file mode 100644
index 0000000..ef7ca8b
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.c
@@ -0,0 +1,171 @@
+/** @file
+ This is the main DXE file for TXT. It represents an abstract outline of the
+ steps required during DXE for enabling TXT. Each individual step is further
+ abstracted behind a function call interface. This is intended to minimize
+ the need to modify this file when porting TXT to future platforms.
+
+@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 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
+
+**/
+
+///
+/// External include files do NOT need to be explicitly specified in real EDKII
+/// environment
+///
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "Txt.h"
+#include "TxtDxeLib.h"
+#endif
+
+TXT_DXE_LIB_CONTEXT mTxtDxeCtx;
+
+/**
+ This function gets registered as a callback to run the SCHECK function
+ from the TXT BIOS ACM as a result of Boot Events.
+
+ @param[in] Event - A pointer to the Event that triggered the callback.
+ @param[in] Context - A pointer to private data registered with the callback function.
+
+ @retval EFI_SUCCESS - Always.
+
+ **/
+EFI_STATUS
+EFIAPI
+ScheckCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ DEBUG ((EFI_D_INFO, "TXTDXE::Running of DoScheck\n"));
+
+ DoScheck (&mTxtDxeCtx);
+ ///
+ /// Closed the event to avoid call twice when launch shell
+ ///
+ gBS->CloseEvent (Event);
+
+ return EFI_SUCCESS;
+}
+/**
+ This is the entry point to the TXT DXE Driver. This routine checks to see if
+ the platform should be configured for TXT and if so, configures the platform
+ by reserving and initializing TXT Configuration Space and TXT Device Memory and
+ registering a callback to run SCHECK from the TXT BIOS ACM prior to boot.
+
+ If the platform should not be configured for TXT, this routine checks the
+ establishment bit in the TPM and resets it if it is asserted.
+
+ @param[in] ImageHandle - A handle for this module
+ @param[in] SystemTable - A pointer to the EFI System Table
+
+ @retval EFI_SUCCESS - If TXT initialization succeed
+ @retval EFI_UNLOAD_IMAGE - If TXT criterias are not met
+**/
+EFI_STATUS
+EFIAPI
+DriverEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT ReadyToBootEvent;
+ ///
+ /// Initialize the platform specific code
+ ///
+ Status = InitializeTxtDxeLib (ImageHandle, SystemTable, &mTxtDxeCtx);
+ ///
+ /// If failure - assume TXT is not enabled
+ ///
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "TXTDXE::InitializeTxtDxeLib failed.... Unloading\n"));
+ return EFI_UNLOAD_IMAGE;
+ }
+ ///
+ /// If ESTS.TXTRESET bit is set, skip all other functions since
+ /// attempt to execute GETSEC will hang system. Skipping allows to
+ /// boot to OS and let MLE assess situation.
+ ///
+ if (IsTxtResetSet (&mTxtDxeCtx)) {
+ DEBUG ((EFI_D_ERROR, "TXTDXE::TXT_RESET bit is set.... Unloading\n"));
+ return EFI_UNLOAD_IMAGE;
+ }
+ ///
+ /// If TXT is enabled, configure platform appropriately.
+ /// Code assumes that if TXT is enabled by CPU driver than all checks
+ /// are passed, i.e. TPM is present, CPU and CS are TXT capable.
+ ///
+ ///
+ /// Add to check CPU TXT capable in case CPU drivers do not check additional requirements
+ ///
+ if ((mTxtDxeCtx.TxtInfoData->ChipsetIsTxtCapable) && IsTxtProcessor () && IsTxtEnabled (&mTxtDxeCtx)) {
+ DEBUG ((EFI_D_INFO, "TXTDXE::TXT Enabled\n"));
+ ///
+ /// Mark TXT Config Space as System Reserved in Memory Map
+ ///
+ ReserveTxtConfigSpace (&mTxtDxeCtx);
+
+ ///
+ /// Allocate and Initialize TXT Device Memory
+ ///
+ Status = SetupTxtDeviceMemory (&mTxtDxeCtx);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "TXTDXE::SetupTxtDeviceMemory failed.... Unloading\n"));
+ return EFI_UNLOAD_IMAGE;
+ }
+ ///
+ /// Create callback to run SCHECK on a Legacy Boot event
+ ///
+ Status = EfiCreateEventReadyToBootEx (
+ EFI_TPL_CALLBACK,
+ ScheckCallback,
+ NULL,
+ &ReadyToBootEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ } else {
+ ///
+ /// TXT is not enabled, so make sure TPM Establishment
+ /// bit is de-asserted
+ ///
+ DEBUG ((EFI_D_INFO, "TXTDXE::TXT Disabled\n"));
+
+ if (IsTxtEstablished (&mTxtDxeCtx)) {
+ ///
+ /// We can invoke BIOS ACM function only if CS and CPU are TXT
+ /// capable
+ ///
+ if ((mTxtDxeCtx.TxtInfoData->ChipsetIsTxtCapable) &&
+ IsTxtProcessor () &&
+ !(mTxtDxeCtx.TxtInfoData->Flags & TPM_INIT_FAILED)
+ ) {
+ DEBUG ((EFI_D_INFO, "TXTDXE::Resetting TPM Establishment bit\n"));
+ ResetTpmEstBit (&mTxtDxeCtx);
+ }
+ }
+ ///
+ /// Reset AUX
+ ///
+ Status = ResetTpmAux (&mTxtDxeCtx);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.cif b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.cif
new file mode 100644
index 0000000..2add449
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.cif
@@ -0,0 +1,18 @@
+<component>
+ name = "TxtDxe"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\Txt\TxtInit\Dxe\"
+ RefName = "TxtDxe"
+[files]
+"TxtDxe.c"
+"TxtDxe.dxs"
+"TxtDxe.mak"
+"TxtDxe.sdl"
+"TxtDxeLib.c"
+"TxtDxeLib.h"
+"TxtDxe.inf"
+"TxtDxeOem.c"
+"x64\TxtDxeBsp.asm"
+"x64\TxtDxeAp.asm"
+"x64\Mmx64.inc"
+<endComponent>
diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.dxs b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.dxs
new file mode 100644
index 0000000..7120727
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.dxs
@@ -0,0 +1,50 @@
+/** @file
+ This is the Dependency expression for the TXT Dxe architectural protocol
+
+@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
+
+**/
+
+
+//
+// Common for R8 and R9 codebase
+//
+#include "AutoGen.h"
+#include "DxeDepex.h"
+
+//
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are both "defined" in R8 codebase;
+// BUILD_WITH_EDKII_GLUE_LIB is defined in Edk-Dev-Snapshot-20070228 and later version
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are "not defined" in R9 codebase.
+//
+#if defined (BUILD_WITH_GLUELIB) || defined (BUILD_WITH_EDKII_GLUE_LIB)
+#include "EfiDepex.h"
+#include EFI_PROTOCOL_DEFINITION (MpService)
+#include EFI_PROTOCOL_DEFINITION (BootScriptSave)
+#include EFI_PROTOCOL_DEFINITION (SmmBase)
+#include EFI_PROTOCOL_DEFINITION (PciIo)
+#include EFI_PROTOCOL_DEFINITION (CpuIo)
+#include EFI_PROTOCOL_DEFINITION (CpuPlatformPolicy)
+#endif
+
+DEPENDENCY_START
+ EFI_BOOT_SCRIPT_SAVE_PROTOCOL_GUID AND
+ EFI_MP_SERVICES_PROTOCOL_GUID AND
+ EFI_SMM_BASE_PROTOCOL_GUID AND
+ DXE_CPU_PLATFORM_POLICY_PROTOCOL_GUID AND
+
+ EFI_CPU_IO_PROTOCOL_GUID
+DEPENDENCY_END
diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.inf b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.inf
new file mode 100644
index 0000000..f6c1e20
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.inf
@@ -0,0 +1,117 @@
+## @file
+# Component description file for TXTDXE module
+#
+#@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
+#
+
+
+[defines]
+BASE_NAME = TxtDxe
+FILE_GUID = FF917E22-A228-448d-BDAA-68EFCCDDA5D3
+COMPONENT_TYPE = BS_DRIVER
+
+[sources.common]
+ TxtDxe.c
+ TxtDxeLib.c
+ TxtDxeOem.c
+ X64/TxtDxeBsp.asm
+ X64/TxtDxeAp.asm
+
+#
+# Edk II Glue Driver Entry Point
+#
+ EdkIIGlueDxeDriverEntryPoint.c
+
+[includes.common]
+ .
+ ./X64
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_SA_ROOT)/Include
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Framework/Protocol
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Sample/Include
+
+#
+# Edk II Glue Library, some hearder are included by R9 header so have to include
+#
+
+ $(EFI_SOURCE)
+ $(EFI_SOURCE)/Framework
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+#
+# Typically the sample code referenced will be available in the code base already
+# So keep this include at the end to defer to the source base definition
+# and only use the sample code definition if source base does not include these files.
+#
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/SampleCode
+
+[libraries.common]
+ EfiGuidLib
+ EdkFrameworkProtocolLib
+ EdkProtocolLib
+ EfiScriptLib
+ CpuGuidLib
+ CpuProtocolLib
+ EdkIIGlueBaseLib
+ EdkIIGlueBaseMemoryLib
+ EdkIIGlueBasePciLibPciExpress
+ EdkIIGlueDxeReportStatusCodeLib
+ EdkIIGlueDxeServicesTableLib
+ EdkIIGlueDxeDebugLibReportStatusCode
+ EdkIIGlueUefiBootServicesTableLib
+ EdkIIGlueUefiRuntimeServicesTableLib
+ EdkIIGlueUefiLib
+ EdkIIGlueDxeHobLib
+ CpuProtocolLib
+
+#
+# Typically the sample code referenced will be available in the code base already
+# So keep this include at the end to defer to the source base definition
+# and only use the sample code definition if source base does not include these files.
+#
+ CpuSampleProtocolLib
+
+[nmake.common]
+ IMAGE_ENTRY_POINT = _ModuleEntryPoint
+ DPX_SOURCE = TxtDxe.dxs
+#
+# Module Entry Point
+#
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=DriverEntry
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_BASE_LIB__ \
+ -D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ -D __EDKII_GLUE_DXE_REPORT_STATUS_CODE_LIB__ \
+ -D __EDKII_GLUE_DXE_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ -D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_UEFI_LIB__ \
+ -D __EDKII_GLUE_DXE_HOB_LIB__
diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.mak b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.mak
new file mode 100644
index 0000000..876fc41
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.mak
@@ -0,0 +1,72 @@
+# MAK file for the ModulePart:TxtDxe
+#-jeff debug
+all : TxtDxe
+
+TxtDxe : $(BUILD_DIR)\TxtDxe.mak TxtDxeBin
+
+$(BUILD_DIR)\TxtDxe.mak : $(TxtDxe_DIR)\$(@B).cif $(TxtDxe_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(TxtDxe_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+TxtDxe_INCLUDES=\
+ $(MISCFRAMEWORK_INCLUDES)\
+ $(EdkIIGlueLib_INCLUDES)\
+ $(PROJECT_CPU_INCLUDES)\
+ $(TXT_INCLUDES)\
+
+TxtDxe_DEFINES=\
+ $(MY_DEFINES)\
+ /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=DriverEntry"\
+ /D PlatformPciExpressBaseAddress=$(PCIEX_BASE_ADDRESS) \
+ /D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ /D __EDKII_GLUE_BASE_LIB__ \
+ /D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ /D __EDKII_GLUE_DXE_REPORT_STATUS_CODE_LIB__ \
+ /D __EDKII_GLUE_DXE_SERVICES_TABLE_LIB__ \
+ /D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ /D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \
+ /D __EDKII_GLUE_UEFI_LIB__ \
+ /D __EDKII_GLUE_UEFI_DEVICE_PATH_LIB__ \
+ /D __EDKII_GLUE_BASE_PCI_LIB_PCI_EXPRESS__ \
+ /D __EDKII_GLUE_DXE_MEMORY_ALLOCATION_LIB__ \
+ /D __EDKII_GLUE_DXE_HOB_LIB__ \
+
+TxtDxe_LIBS=\
+ $(EFIGUIDLIB)\
+ $(EDKFRAMEWORKPROTOCOLLIB)\
+ $(EDKPROTOCOLLIB)\
+ $(EdkIIGlueBaseIoLibIntrinsic_LIB)\
+ $(EdkIIGlueBaseLib_LIB)\
+ $(EdkIIGlueBaseLibX64_LIB)\
+ $(EdkIIGlueBaseMemoryLib_LIB)\
+ $(EdkIIGlueDxeReportStatusCodeLib_LIB)\
+ $(EdkIIGlueDxeServicesTableLib_LIB)\
+ $(EdkIIGlueDxeDebugLibReportStatusCode_LIB)\
+ $(EdkIIGlueUefiBootServicesTableLib_LIB)\
+ $(EdkIIGlueUefiLib_LIB)\
+ $(EdkIIGlueBasePciLibPciExpress_LIB)\
+ $(EdkIIGlueBasePciExpressLib_LIB)\
+ $(EdkIIGlueDxeMemoryAllocationLib_LIB)\
+ $(EdkIIGlueBaseTimerLibLocalApic_LIB)\
+ $(EdkIIGlueDxeHobLib_LIB)\
+ $(EdkIIGlueHiiLib_LIB)\
+ $(EFIDRIVERLIB)\
+ $(UEFIEFIIFRSUPPORTLIB)\
+ $(EFISCRIPTLIB)\
+ $(CpuProtocolLib_LIB)\
+ $(CpuGuidLib_LIB)\
+ $(SaPcieDxeLib_LIB)\
+ $(CPUIA32LIB)
+
+TxtDxeBin : $(TxtDxe_LIBS)
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\TxtDxe.mak all\
+ "MY_INCLUDES=$(TxtDxe_INCLUDES)"\
+ "MY_DEFINES=$(TxtDxe_DEFINES)"\
+ "GUID=FF917E22-A228-448d-BDAA-68EFCCDDA5D3"\
+ "AFLAGS=$(AFLAGS) $(PROJECT_CPU_INCLUDES)"\
+ ENTRY_POINT=_ModuleEntryPoint \
+ TYPE=BS_DRIVER \
+ EDKIIModule=DXEDRIVER\
+ DEPEX1=$(TxtDxe_DIR)\TxtDxe.dxs\
+ DEPEX1_TYPE=EFI_SECTION_DXE_DEPEX\
+ COMPRESS=1\
diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.sdl b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.sdl
new file mode 100644
index 0000000..c17f497
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxe.sdl
@@ -0,0 +1,27 @@
+TOKEN
+ Name = "TxtDxe_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable TXT DXE init support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+End
+
+PATH
+ Name = "TxtDxe_DIR"
+ Help = "TXT DXE source directory"
+End
+
+MODULE
+ Help = "Includes TXTDXE.mak into project"
+ File = "TXTDXE.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\TxtDxe.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End
+ \ No newline at end of file
diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxeLib.c b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxeLib.c
new file mode 100644
index 0000000..6aef615
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxeLib.c
@@ -0,0 +1,1080 @@
+/** @file
+ This file contains an implementation of the function call interfaces
+ required by the main TXT DXE file. Hopefully, future platform porting
+ tasks will be mostly limited to modifying the functions in this file.
+
+@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 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
+
+**/
+
+///
+/// External include files do NOT need to be explicitly specified in real EDKII
+/// environment
+///
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "Txt.h"
+#include "TxtDxeLib.h"
+#include "EfiScriptLib.h"
+#include EFI_PROTOCOL_DEFINITION (PciIo)
+#include EFI_PROTOCOL_DEFINITION (PciRootBridgeIo)
+#include EFI_PROTOCOL_DEPENDENCY (FirmwareVolume)
+#endif
+
+EFI_GUID mTxtBiosAcmPeiFileGuid = PEI_BIOS_ACM_FILE_GUID;
+
+UINT64 mMcuAddr;
+UINT64 mAcmBase;
+UINT64 mApMtrrTab[2 * (IA32_MTRR_PHYSMASK9 - IA32_MTRR_PHYSBASE0 + 1) + 1];
+UINT64 mApIdt[2];
+UINT64 mApCr4;
+UINT64 mApSavedIa32ThermInterruptMSR[2];
+UINT32 mApSavedApicThermalValue;
+
+/**
+ This routine initializes and collects all Protocols and data required
+ by the routines in this file.
+
+ @param[in] ImageHandle - A pointer to the Image Handle for this file.
+ @param[in] SystemTable - A pointer to the EFI System Table
+ @param[in] TxtDxeCtx - A pointer to a caller allocated data structure that contains
+ all of the Protocols and data required by the routines
+ in this file.
+
+ @retval EFI_SUCCESS - Return EFI_SUCCESS if no error happen
+ @retval EFI_UNLOAD_IMAGE - If TxtInfoHob is not found
+**/
+EFI_STATUS
+InitializeTxtDxeLib (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable,
+ IN OUT TXT_DXE_LIB_CONTEXT *TxtDxeCtx
+ )
+{
+ EFI_STATUS Status;
+ VOID *HobList;
+ TXT_INFO_HOB *TxtInfoHob;
+ UINTN tmp;
+
+ INITIALIZE_SCRIPT (ImageHandle, SystemTable);
+
+ TxtDxeCtx->ImageHandle = ImageHandle;
+ TxtDxeCtx->SystemTable = SystemTable;
+
+ ///
+ /// Find the TxtPolicyprotocol
+ ///
+ Status = gBS->LocateProtocol (
+ &gDxeCpuPlatformPolicyProtocolGuid,
+ NULL,
+ (VOID **) &(TxtDxeCtx->CpuPlatformPolicy)
+ );
+
+ if (EFI_ERROR (Status)) {
+ TxtDxeCtx->CpuPlatformPolicy = NULL;
+ }
+ ///
+ /// Find the CpuIo protocol
+ ///
+ Status = gBS->LocateProtocol (
+ &gEfiCpuIoProtocolGuid,
+ NULL,
+ (VOID **) &(TxtDxeCtx->CpuIo)
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ ///
+ /// Find the MpService Protocol
+ ///
+ Status = gBS->LocateProtocol (
+ &gEfiMpServiceProtocolGuid,
+ NULL,
+ (VOID **) &(TxtDxeCtx->MpService)
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ ///
+ /// Initialize CpuCount info. Current implemetation of
+ /// GetGeneralMPInfo doesn't honor optionality of arguments. Don't use
+ /// NULL pointers.
+ ///
+ Status = TxtDxeCtx->MpService->GetGeneralMPInfo (
+ TxtDxeCtx->MpService,
+ &(TxtDxeCtx->CpuCount),
+ &tmp,
+ &tmp,
+ &tmp,
+ &tmp
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Find TxtInfoHob
+ ///
+ HobList = GetFirstGuidHob (&gTxtInfoHobGuid);
+ if (HobList == NULL) {
+ return EFI_UNLOAD_IMAGE;
+ }
+
+ TxtInfoHob = (TXT_INFO_HOB *) HobList;
+ TxtDxeCtx->TxtInfoData = &(TxtInfoHob->Data);
+
+ ///
+ /// Print out the TxtInfo HOB
+ ///
+ DEBUG ((EFI_D_INFO, "TXTDXE: TxtInfoHob passed from platform as:\n"));
+ DEBUG ((EFI_D_INFO, "TXTDXE: ChipsetIsTxtCapable = %x\n", TxtDxeCtx->TxtInfoData->ChipsetIsTxtCapable));
+ DEBUG ((EFI_D_INFO, "TXTDXE: TxtMode = %x\n", TxtDxeCtx->TxtInfoData->TxtMode));
+ DEBUG ((EFI_D_INFO, "TXTDXE: PmBase = %x\n", TxtDxeCtx->TxtInfoData->PmBase));
+ DEBUG ((EFI_D_INFO, "TXTDXE: SinitMemorySize = %x\n", TxtDxeCtx->TxtInfoData->SinitMemorySize));
+ DEBUG ((EFI_D_INFO, "TXTDXE: TxtHeapMemorySize = %x\n", TxtDxeCtx->TxtInfoData->TxtHeapMemorySize));
+ DEBUG ((EFI_D_INFO, "TXTDXE: TxtDprMemoryBase = %x\n", TxtDxeCtx->TxtInfoData->TxtDprMemoryBase));
+ DEBUG ((EFI_D_INFO, "TXTDXE: TxtDprMemorySize = %x\n", TxtDxeCtx->TxtInfoData->TxtDprMemorySize));
+ DEBUG ((EFI_D_INFO, "TXTDXE: BiosAcmBase = %x\n", TxtDxeCtx->TxtInfoData->BiosAcmBase));
+ DEBUG ((EFI_D_INFO, "TXTDXE: BiosAcmSize = %x\n", TxtDxeCtx->TxtInfoData->BiosAcmSize));
+ DEBUG ((EFI_D_INFO, "TXTDXE: McuUpdateDataAddr = %x\n", TxtDxeCtx->TxtInfoData->McuUpdateDataAddr));
+ DEBUG ((EFI_D_INFO, "TXTDXE: SinitAcmBase = %x\n", TxtDxeCtx->TxtInfoData->SinitAcmBase));
+ DEBUG ((EFI_D_INFO, "TXTDXE: SinitAcmSize = %x\n", TxtDxeCtx->TxtInfoData->SinitAcmSize));
+ DEBUG ((EFI_D_INFO, "TXTDXE: TgaSize = %x\n", TxtDxeCtx->TxtInfoData->TgaSize));
+ DEBUG ((EFI_D_INFO, "TXTDXE: TxtLcpPdBase = %x\n", TxtDxeCtx->TxtInfoData->TxtLcpPdBase));
+ DEBUG ((EFI_D_INFO, "TXTDXE: TxtLcpPdSize = %x\n", TxtDxeCtx->TxtInfoData->TxtLcpPdSize));
+ DEBUG ((EFI_D_INFO, "TXTDXE: Flags = %x\n", TxtDxeCtx->TxtInfoData->Flags));
+ return EFI_SUCCESS;
+}
+
+/**
+ Determines whether or not the platform has executed an TXT launch by
+ examining the TPM Establishment bit.
+
+ @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure
+
+ @retval TRUE - If the TPM establishment bit is asserted.
+ @retval FALSE - If the TPM establishment bit is unasserted.
+**/
+BOOLEAN
+IsTxtEstablished (
+ IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx
+ )
+{
+ EFI_STATUS Status;
+ UINT8 AccessReg;
+ UINT16 TimeOutCount;
+
+ ///
+ /// TO-DO: We might locate TCG protocol to access TPM status
+ ///
+ ///
+ /// Set TPM.ACCESS polling timeout about 750ms
+ ///
+ TimeOutCount = TPM_TIME_OUT;
+ do {
+ ///
+ /// Read TPM status register
+ ///
+ Status = TxtDxeCtx->CpuIo->Mem.Read (
+ TxtDxeCtx->CpuIo,
+ EfiCpuIoWidthUint8,
+ (UINT64) TPM_STATUS_REG_ADDRESS,
+ 1,
+ &AccessReg
+ );
+ ASSERT_EFI_ERROR (Status);
+ ///
+ /// if TPM.Access == 0xFF, TPM is not present
+ ///
+ if (AccessReg == 0xFF) {
+ return FALSE;
+ }
+ ///
+ /// Check tpmRegValidSts bit before checking establishment bit
+ ///
+ if ((AccessReg & 0x80) != 0x80) {
+ ///
+ /// Delay 1ms and read again
+ ///
+ gBS->Stall (1000);
+ } else {
+ ///
+ /// tpmRegValidSts set, we can check establishment bit now.
+ ///
+ break;
+ }
+
+ TimeOutCount--;
+ } while (TimeOutCount != 0);
+
+ ///
+ /// if tpmRegValidSts is not set, TPM is not usable
+ ///
+ if ((AccessReg & 0x80) != 0x80) {
+ DEBUG ((EFI_D_ERROR, "TXTDXE: TPM Valid Status is not set!! TPM.ACCESS=%x\n", AccessReg));
+ ASSERT (TRUE);
+ EFI_DEADLOOP ();
+ }
+ ///
+ /// The bit we're interested in uses negative logic:
+ /// If bit 0 == 1 then return False
+ /// Else return True
+ ///
+ return (AccessReg & 0x1) ? FALSE : TRUE;
+}
+
+/**
+ Determines whether or not the platform has executed an TXT launch by
+ examining the TPM Establishment bit.
+
+ @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure
+
+ @retval TRUE - If the TPM establishment bit is asserted.
+ @retval FALSE - If the TPM establishment bit is unasserted.
+**/
+BOOLEAN
+IsTxtResetSet (
+ IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx
+ )
+{
+ EFI_STATUS Status;
+ UINT8 EstsReg;
+
+ ///
+ /// TO-DO: We might locate TCG protocol to access TPM status
+ ///
+ ///
+ /// Read TPM status register
+ ///
+ Status = TxtDxeCtx->CpuIo->Mem.Read (
+ TxtDxeCtx->CpuIo,
+ EfiCpuIoWidthUint8,
+ (UINT64) TXT_PUBLIC_BASE + TXT_ERROR_STATUS_REG_OFF,
+ 1,
+ &EstsReg
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return (EstsReg & 0x1) ? TRUE : FALSE;
+}
+
+/**
+ Determines whether or not the platform requires initialization for TXT use.
+
+ @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure
+
+ @retval TRUE - If the the platoform should be configured for TXT.
+ @retval FALSE - If TXT is not to be used.
+**/
+BOOLEAN
+IsTxtEnabled (
+ IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx
+ )
+{
+
+ UINT64 Ia32FeatureControl;
+ TXT_INFO_DATA *TxtInfoData;
+
+ TxtInfoData = TxtDxeCtx->TxtInfoData;
+
+ ///
+ /// If TxtInfoHob reported TXT disabled, return FALSE to indicate TXT should be be used
+ ///
+ if (TxtInfoData->TxtMode == 0) {
+ return FALSE;
+ }
+
+ Ia32FeatureControl = AsmReadMsr64 (MSR_IA32_FEATURE_CONTROL);
+
+ return ((Ia32FeatureControl & TXT_OPT_IN_VMX_AND_SMX_MSR_VALUE) == TXT_OPT_IN_VMX_AND_SMX_MSR_VALUE) ? TRUE : FALSE;
+}
+
+/**
+ Determines whether or not the current processor is TXT Capable.
+
+ @retval TRUE - If the current processor supports TXT
+ @retval FALSE - If the current processor does not support TXT
+**/
+BOOLEAN
+IsTxtProcessor (
+ VOID
+ )
+{
+ EFI_CPUID_REGISTER CpuidRegs;
+
+ AsmCpuid (1, &CpuidRegs.RegEax, &CpuidRegs.RegEbx, &CpuidRegs.RegEcx, &CpuidRegs.RegEdx);
+
+ return (CpuidRegs.RegEcx & B_CPUID_VERSION_INFO_ECX_SME) ? TRUE : FALSE;
+}
+
+/**
+ Add extened elements to BiosOsData
+
+ @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure
+ @param[in] Type - The element's type
+ @param[in] Buffer - A pointer to buffer which need to append the element
+ @param[in] Size - return the size of the appened element.
+
+ @retval None
+**/
+VOID
+AppendElement (
+ IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx,
+ IN UINT32 Type,
+ IN VOID *Buffer,
+ OUT UINT32 *Size
+ )
+{
+ VOID *Element;
+ UINT32 NumberOfAcm;
+ UINT64 *AcmBase;
+
+ NumberOfAcm = 1;
+ AcmBase = NULL;
+ Element = NULL;
+ *Size = 0;
+
+ switch (Type) {
+ case HEAP_EXTDATA_TYPE_BIOS_SPEC_VER:
+ ///
+ /// Fill BIOS spec ver element
+ ///
+ Element = AllocatePool (sizeof (HEAP_BIOS_SPEC_VER_ELEMENT));
+
+ if (Element != NULL) {
+ *Size = sizeof (HEAP_BIOS_SPEC_VER_ELEMENT);
+ ((HEAP_BIOS_SPEC_VER_ELEMENT *) Element)->Header.Type = HEAP_EXTDATA_TYPE_BIOS_SPEC_VER;
+ ((HEAP_BIOS_SPEC_VER_ELEMENT *) Element)->Header.Size = sizeof (HEAP_BIOS_SPEC_VER_ELEMENT);
+ ((HEAP_BIOS_SPEC_VER_ELEMENT *) Element)->SpecVerMajor = TXT_BIOS_SPEC_VER_MAJOR;
+ ((HEAP_BIOS_SPEC_VER_ELEMENT *) Element)->SpecVerMinor = TXT_BIOS_SPEC_VER_MINOR;
+ ((HEAP_BIOS_SPEC_VER_ELEMENT *) Element)->SpecVerRevision = TXT_BIOS_SPEC_VER_REVISION;
+ }
+ break;
+
+ case HEAP_EXTDATA_TYPE_BIOSACM:
+ ///
+ /// Fill BIOS ACM element
+ ///
+ Element = AllocatePool (sizeof (HEAP_BIOSACM_ELEMENT) + NumberOfAcm * sizeof (UINT64));
+
+ if (Element != NULL) {
+ *Size = sizeof (HEAP_BIOSACM_ELEMENT) + sizeof (UINT64) * NumberOfAcm;
+ ((HEAP_BIOSACM_ELEMENT *) Element)->Header.Type = HEAP_EXTDATA_TYPE_BIOSACM;
+ ((HEAP_BIOSACM_ELEMENT *) Element)->Header.Size = sizeof (HEAP_BIOSACM_ELEMENT) + NumberOfAcm * sizeof (UINT64);
+ ((HEAP_BIOSACM_ELEMENT *) Element)->NumAcms = NumberOfAcm;
+ AcmBase = (UINT64 *) ((UINTN) Element + sizeof (HEAP_BIOSACM_ELEMENT));
+ *AcmBase = TxtDxeCtx->TxtInfoData->BiosAcmBase;
+ }
+ break;
+
+ case HEAP_EXTDATA_TYPE_END:
+ ///
+ /// Fill end type element
+ ///
+ Element = AllocatePool (sizeof (HEAP_EXT_DATA_ELEMENT));
+
+ if (Element != NULL) {
+ *Size = sizeof (HEAP_EXT_DATA_ELEMENT);
+ ((HEAP_EXT_DATA_ELEMENT *) Element)->Type = HEAP_EXTDATA_TYPE_END;
+ ((HEAP_EXT_DATA_ELEMENT *) Element)->Size = sizeof (HEAP_EXT_DATA_ELEMENT);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (Element != NULL) {
+ CopyMem (Buffer, Element, *Size);
+ FreePool (Element);
+ }
+}
+
+/**
+ Allocates 1 MB of 1MB-aligned memory for use as TXT Device Memory. Records
+ the location of TXT Device Memory in TXT Chipset registers and then adds
+ programming instructions for these registers into BootScript.
+
+ @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure
+
+ @retval EFI_SUCCESS - TXT Device memory has been successfully initialized.
+ @exception EFI_UNSUPPORTED - TXT Device memory not available.
+**/
+EFI_STATUS
+SetupTxtDeviceMemory (
+ IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx
+ )
+{
+ EFI_PHYSICAL_ADDRESS TopAddr;
+ UINT64 *Ptr64;
+ UINT64 Value64;
+ UINT32 Value32;
+ UINT64 TxtHeapMemoryBase;
+ UINT64 TxtSinitMemoryBase;
+ BOOLEAN Locked;
+ BIOS_OS_DATA_REGION *BiosOsDataRegion;
+ TXT_INFO_DATA *TxtInfoData;
+ UINT8 *Ptr8;
+
+ TxtHeapMemoryBase = 0;
+ TxtSinitMemoryBase = 0;
+ Locked = FALSE;
+ Ptr8 = NULL;
+ Value32 = 0;
+
+ TxtInfoData = TxtDxeCtx->TxtInfoData;
+
+ if ((TxtInfoData == 0) ||
+ (TxtInfoData->TxtDprMemoryBase == 0) ||
+ (TxtInfoData->TxtDprMemorySize == 0) ||
+ (TxtInfoData->TxtHeapMemorySize == 0) ||
+ (TxtInfoData->SinitMemorySize == 0)
+ ) {
+ return EFI_UNSUPPORTED;
+ } else {
+ ///
+ /// Use address passed from PEI
+ ///
+ TopAddr = TxtInfoData->TxtDprMemoryBase + TxtInfoData->TxtDprMemorySize;
+
+ TxtHeapMemoryBase = (UINT64) (TopAddr - TxtInfoData->TxtHeapMemorySize);
+
+ TxtSinitMemoryBase = TxtHeapMemoryBase - TxtInfoData->SinitMemorySize;
+ }
+ ///
+ /// Program TXT Device Memory Chipset Registers and record them in
+ /// BootScript so they will be saved and restored on S3
+ ///
+ ASSERT ((TopAddr & 0x0FFFFF) == 0);
+
+ ///
+ /// DPR registers
+ ///
+ Ptr64 = (UINT64 *) (UINTN) (TXT_PUBLIC_BASE + TXT_DPR_SIZE_REG_OFF);
+ Value64 = RShiftU64 (TxtInfoData->TxtDprMemorySize, 16) | 1;
+ *Ptr64 = Value64 | TopAddr;
+ ///
+ /// Assert error if programmed value is different from requested. This
+ /// means error is requested size.
+ ///
+ Value64 = *Ptr64;
+ ASSERT ((LShiftU64 ((Value64 & 0xFFE), 16)) == TxtInfoData->TxtDprMemorySize);
+
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINT64) (UINTN) (Ptr64),
+ 2,
+ &Value64
+ );
+
+ ///
+ /// HEAP Registers
+ /// Program size register first
+ ///
+ Ptr64 = (UINT64 *) (UINTN) (TXT_PUBLIC_BASE + TXT_HEAP_SIZE_REG_OFF);
+
+ ///
+ /// Test register locked status. If locked, skip programming since
+ /// this will be done by BIOS ACM
+ ///
+ *Ptr64 = TEST_PATTERN;
+ Value64 = *Ptr64;
+ if (Value64 != TEST_PATTERN) {
+ Locked = TRUE;
+ } else {
+ ///
+ /// To be safe invert pattern and try again
+ ///
+ *Ptr64 = (UINT64) ~TEST_PATTERN;
+ Value64 = *Ptr64;
+ if (Value64 != (UINT64) ~TEST_PATTERN) {
+ Locked = TRUE;
+ }
+ }
+
+ if (!Locked) {
+
+ *Ptr64 = TxtInfoData->TxtHeapMemorySize;
+ ///
+ /// Assert error if programmed value is different from requested. This
+ /// means error is requested size.
+ ///
+ Value64 = *Ptr64;
+ ASSERT (Value64 == TxtInfoData->TxtHeapMemorySize);
+
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINT64) (UINTN) (Ptr64),
+ 2,
+ &Value64
+ );
+
+ ///
+ /// Program base register.
+ ///
+ Ptr64 = (UINT64 *) (UINTN) (TXT_PUBLIC_BASE + TXT_HEAP_BASE_REG_OFF);
+ *Ptr64 = TxtHeapMemoryBase;
+
+ ///
+ /// Assert error if programmed value is different from requested. This
+ /// means error is requested size.
+ ///
+ Value64 = *Ptr64;
+ ASSERT (Value64 == TxtHeapMemoryBase);
+
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINT64) (UINTN) (Ptr64),
+ 2,
+ &Value64
+ );
+ }
+ ///
+ /// SINIT Registers
+ /// Program size register first
+ ///
+ Ptr64 = (UINT64 *) (UINTN) (TXT_PUBLIC_BASE + TXT_SINIT_SIZE_REG_OFF);
+ *Ptr64 = TxtInfoData->SinitMemorySize;
+ ///
+ /// Assert error if programmed value is different from requested. This
+ /// means error is requested size.
+ ///
+ Value64 = *Ptr64;
+ ASSERT (Value64 == TxtInfoData->SinitMemorySize);
+
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINT64) (UINTN) (Ptr64),
+ 2,
+ &Value64
+ );
+
+ ///
+ /// Program base register
+ ///
+ Ptr64 = (UINT64 *) (UINTN) (TXT_PUBLIC_BASE + TXT_SINIT_BASE_REG_OFF);
+ *Ptr64 = TxtSinitMemoryBase;
+ ///
+ /// Assert error if programmed value is different from requested. This
+ /// means error is requested size.
+ ///
+ Value64 = *Ptr64;
+ ASSERT (Value64 == TxtSinitMemoryBase);
+
+ SCRIPT_MEM_WRITE (
+ EFI_ACPI_S3_RESUME_SCRIPT_TABLE,
+ EfiBootScriptWidthUint32,
+ (UINT64) (UINTN) (Ptr64),
+ 2,
+ &Value64
+ );
+
+ ///
+ /// Make sure TXT Device Memory has been zeroed
+ ///
+ ZeroMem (
+ (VOID *) ((UINTN) TxtSinitMemoryBase),
+ (UINTN) (TopAddr - TxtSinitMemoryBase)
+ );
+
+ if (TxtInfoData->TgaSize) {
+ ;
+ ///
+ /// Placeholder for Trusted graphics support
+ ///
+ }
+
+ Ptr64 = (UINT64 *) TxtHeapMemoryBase;
+ *Ptr64 = sizeof (BIOS_OS_DATA_REGION);
+ ///
+ /// BiosOsDataSize plus sizew of data size feld itself
+ ///
+ BiosOsDataRegion = (BIOS_OS_DATA_REGION *) (Ptr64 + 1);
+ BiosOsDataRegion->Version = BIOS_OS_DATAREGION_VERSION;
+ BiosOsDataRegion->BiosSinitSize = 0;
+ BiosOsDataRegion->LcpPdBase = TxtInfoData->TxtLcpPdBase;
+ BiosOsDataRegion->LcpPdSize = TxtInfoData->TxtLcpPdSize;
+ BiosOsDataRegion->NumOfLogicalProcessors = (UINT32) (TxtDxeCtx->CpuCount);
+ BiosOsDataRegion->Flags = TxtInfoData->Flags;
+ Ptr8 = (UINT8 *) (UINTN) &(BiosOsDataRegion->ExtData);
+ AppendElement (TxtDxeCtx, HEAP_EXTDATA_TYPE_BIOS_SPEC_VER, Ptr8, &Value32);
+ Ptr8 += Value32;
+ AppendElement (TxtDxeCtx, HEAP_EXTDATA_TYPE_BIOSACM, Ptr8, &Value32);
+ Ptr8 += Value32;
+ AppendElement (TxtDxeCtx, HEAP_EXTDATA_TYPE_END, Ptr8, &Value32);
+ Value64 = (UINT64) Ptr8 - TxtHeapMemoryBase + Value32;
+ *Ptr64 = Value64;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Adds and allocates architecturally defined TXT Configuration Space memory
+ region to GCD.
+
+ @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure
+
+ @retval EFI_SUCCESS - Always.
+**/
+EFI_STATUS
+ReserveTxtConfigSpace (
+ IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS BaseAddr;
+
+ BaseAddr = TXT_PRIVATE_BASE;
+ Status = gDS->AddMemorySpace (
+ EfiGcdMemoryTypeReserved,
+ TXT_PRIVATE_BASE,
+ TXT_CONFIG_SPACE_LENGTH,
+ 0
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gDS->AllocateMemorySpace (
+ EfiGcdAllocateAddress,
+ EfiGcdMemoryTypeReserved,
+ 12, ///< 4K Boundary
+ TXT_CONFIG_SPACE_LENGTH,
+ &BaseAddr,
+ TxtDxeCtx->ImageHandle,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Invokes TxtDxeLibLaunchBiosAcm to execute the SCHECK function.
+
+ @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure
+
+ @retval EFI_SUCCESS - Always.
+**/
+EFI_STATUS
+DoScheck (
+ IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx
+ )
+{
+ return TxtDxeLibLaunchBiosAcm (TxtDxeCtx, TXT_LAUNCH_SCHECK);
+}
+
+/**
+ Invokes TxtDxeLibLaunchBiosAcm to reset the TPM's establishment bit.
+
+ @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure
+
+ @retval EFI_SUCCESS - Always.
+**/
+EFI_STATUS
+ResetTpmEstBit (
+ IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx
+ )
+{
+ return TxtDxeLibLaunchBiosAcm (TxtDxeCtx, TXT_RESET_EST_BIT);
+}
+
+/**
+ Sets up the system and then launches the TXT BIOS ACM to run the function
+ requested by AcmFunction.
+
+ @param[in] AcmFunction - Constant that represents the function from the BIOS ACM
+ that should be executed.
+ @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure
+
+ @retval EFI_SUCCESS - BIOS ACM is set up.
+ @retval EFI_INVALID_PARAMETER - Wrong data in TxtInfoHob.
+ @retval EFI_NOT_FOUND - BIOS ACM is not found
+**/
+EFI_STATUS
+TxtDxeLibLaunchBiosAcm (
+ IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx,
+ IN UINT64 AcmFunction
+ )
+{
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+ UINTN CpuCount;
+ UINTN MyCpuNumber;
+ UINTN Index;
+ UINTN i;
+ EFI_MP_SERVICES_PROTOCOL *MpService;
+
+ UINTN NoHandles;
+ EFI_HANDLE *Buffer;
+ UINTN Size;
+ UINT32 FvStatus;
+ EFI_FV_FILETYPE FileType;
+ EFI_FIRMWARE_VOLUME_PROTOCOL *FwVol;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ UINTN NumPages;
+ EFI_PHYSICAL_ADDRESS Addr;
+ EFI_PHYSICAL_ADDRESS AlignedAddr;
+
+ FwVol = NULL;
+ ///
+ /// Initialize local variables
+ ///
+ CpuCount = TxtDxeCtx->CpuCount;
+ MpService = TxtDxeCtx->MpService;
+ Size = 0;
+ FvStatus = 0;
+ NumPages = 0;
+ Addr = 0;
+
+ if (TxtDxeCtx->TxtInfoData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ ///
+ /// Get current running CPU number
+ ///
+ Status = MpService->WhoAmI (
+ MpService,
+ &MyCpuNumber
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if ((TxtDxeCtx->TxtInfoData->BiosAcmBase == 0) || (TxtDxeCtx->TxtInfoData->BiosAcmSize == 0)) {
+ ///
+ /// If no information about placement of TXT BIOS ACM has been
+ /// passed from PEI - find it and load into memory dynamically.
+ ///
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiFirmwareVolumeProtocolGuid,
+ NULL,
+ &NoHandles,
+ &Buffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ for (i = 0; i < NoHandles; i++) {
+
+ Status = gBS->HandleProtocol (
+ Buffer[i],
+ &gEfiFirmwareVolumeProtocolGuid,
+ (VOID **) &FwVol
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// No output buffer - get size only
+ ///
+ Status = FwVol->ReadFile (
+ FwVol,
+ &mTxtBiosAcmPeiFileGuid,
+ NULL,
+ &Size,
+ &FileType,
+ &Attributes,
+ &FvStatus
+ );
+ if (Status == EFI_SUCCESS) {
+ break;
+ }
+ }
+
+ ASSERT (Size);
+ ///
+ /// Assert if file not found.
+ ///
+ FreePool (Buffer);
+
+ if (FwVol == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ ///
+ /// Allocate 4K aligned memory to load BIOS ACM. For this allocate
+ /// 1 page more than BIOS ACM size.
+ ///
+ NumPages = (Size + EFI_PAGE_SIZE - 1) / EFI_PAGE_SIZE;
+
+ ///
+ /// Allocate buffer for BIOS ACM
+ ///
+ Status = (gBS->AllocatePages) (AllocateAnyPages, EfiRuntimeServicesData, NumPages, &Addr);
+
+ ASSERT_EFI_ERROR (Status);
+
+ AlignedAddr = Addr &~(EFI_PAGE_SIZE - 1);
+ AlignedAddr = AlignedAddr < Addr ? (AlignedAddr + EFI_PAGE_SIZE) : AlignedAddr;
+
+ ///
+ /// Read BIOS ACM into prepared buffer.
+ ///
+ Status = FwVol->ReadFile (
+ FwVol,
+ &mTxtBiosAcmPeiFileGuid,
+ ((VOID **) &AlignedAddr),
+ &Size,
+ &FileType,
+ &Attributes,
+ &FvStatus
+ );
+ } else {
+ ///
+ /// Use address passed from PEI
+ ///
+ AlignedAddr = TxtDxeCtx->TxtInfoData->BiosAcmBase;
+ }
+ ///
+ /// Save AP configuration. Run on one AP since all must be programmed
+ /// identically
+ ///
+ MpService->StartupThisAP (
+ MpService,
+ (EFI_AP_PROCEDURE) ApSaveConfig,
+ 1,
+ NULL,
+ 0,
+ NULL
+ );
+
+ ///
+ /// Initialize APs. Prepare data for DoApInit
+ ///
+ mAcmBase = AlignedAddr;
+ mMcuAddr = TxtDxeCtx->TxtInfoData->McuUpdateDataAddr;
+
+ DisableSmiSources (TxtDxeCtx, TRUE);
+
+#if defined(TXT_RLP_INIT) && (TXT_RLP_INIT == 1)
+ ///
+ /// Execute DoApInit on every AP
+ ///
+ MpService->StartupAllAPs (
+ MpService,
+ (EFI_AP_PROCEDURE) DoApInit,
+ TRUE,
+ NULL,
+ MP_TIMEOUT_FOR_STARTUP_ALL_APS,
+ NULL,
+ NULL
+ );
+#endif
+ ///
+ /// Disable every AP and put in WFS state
+ ///
+ for (Index = 0; Index < CpuCount; Index++) {
+ if (Index != MyCpuNumber) {
+ ///
+ /// Halt CPU otherwise it will not be re-enabled
+ ///
+ Status = MpService->EnableDisableAP (
+ MpService,
+ Index,
+ FALSE,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = MpService->SendIPI (
+ MpService,
+ Index,
+ 0,
+ DELIVERY_MODE_INIT
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+ ///
+ /// Launch the BIOS ACM to run the requested function
+ ///
+ OldTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL);
+
+ LaunchBiosAcm (AlignedAddr, AcmFunction);
+
+ gBS->RestoreTPL (OldTpl);
+
+ ///
+ /// Free memory only if it was allocated
+ ///
+ if (Addr != 0) {
+ (gBS->FreePages)(Addr, NumPages);
+ }
+ ///
+ /// Restart APs
+ ///
+ for (Index = 0; Index < CpuCount; Index++) {
+ if (Index != MyCpuNumber) {
+ Status = MpService->EnableDisableAP (
+ MpService,
+ Index,
+ TRUE,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+ ///
+ /// Restore AP configuration
+ ///
+ Status = MpService->StartupAllAPs (
+ MpService,
+ (EFI_AP_PROCEDURE) ApRestoreConfig,
+ TRUE,
+ NULL,
+ MP_TIMEOUT_FOR_STARTUP_ALL_APS,
+ NULL,
+ NULL
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ DisableSmiSources (TxtDxeCtx, FALSE);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Disable or restore possible SMI sources before or after POST SCHECK
+
+ @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure
+ @param[in] Operation - Boolean value telling what operation is requested:
+ TRUE - to save and then disable possible SMI sources
+ FALSE - to restore original SMI settings
+
+ @retval EFI_SUCCESS - always return EFI_SUCCESS
+**/
+EFI_STATUS
+DisableSmiSources (
+ IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx,
+ IN BOOLEAN Operation
+ )
+{
+ EFI_STATUS Status;
+ UINT64 GlobalSmiControlIoAddr;
+ UINT32 LocalApicBaseAddr;
+ static UINT64 SavedIa32ThermInterruptMSR;
+ static UINT32 SavedSmiControl;
+ static UINT32 SavedApicThermalValue;
+ BOOLEAN x2ApicEnabled;
+
+ x2ApicEnabled = (BOOLEAN) (((AsmReadMsr64 (MSR_IA32_APIC_BASE)) & (BIT11 + BIT10)) == BIT11 + BIT10);
+ GlobalSmiControlIoAddr = TxtDxeCtx->TxtInfoData->PmBase + 0x30;
+ LocalApicBaseAddr = ((UINT32) AsmReadMsr64 (MSR_IA32_APIC_BASE)) & BASE_ADDR_MASK;
+
+ if (Operation == TRUE) {
+ ///
+ /// Save IA32_THERMAL_INTERRUPT MSR and disable the interrupts
+ ///
+ SavedIa32ThermInterruptMSR = AsmReadMsr64 ((UINT32) IA32_THERM_INTERRUPT);
+ AsmWriteMsr64 (
+ (UINT32) IA32_THERM_INTERRUPT,
+ (UINT64) (SavedIa32ThermInterruptMSR &~(BIT0 + BIT1 + BIT2 + BIT4 + BIT15 + BIT23))
+ );
+ ///
+ /// Save THERMAL LVT in local APIC and mask THERMAL LVT
+ ///
+ if (x2ApicEnabled) {
+ SavedApicThermalValue = (UINT32) AsmReadMsr64 (MSR_EXT_XAPIC_LVT_THERM);
+ AsmWriteMsr64 (
+ MSR_EXT_XAPIC_LVT_THERM,
+ ((SavedApicThermalValue &~(B_INTERRUPT_MASK | B_DELIVERY_MODE | B_VECTOR)) | (B_INTERRUPT_MASK | V_MODE_SMI))
+ );
+ } else {
+ SavedApicThermalValue = *(UINT32 *) (UINTN) (LocalApicBaseAddr + LOCAL_APIC_THERMAL_DEF);
+ *(UINT32 *) (UINTN) (LocalApicBaseAddr + LOCAL_APIC_THERMAL_DEF) = (UINT32) ((SavedApicThermalValue &~(B_INTERRUPT_MASK | B_DELIVERY_MODE | B_VECTOR)) | (B_INTERRUPT_MASK | V_MODE_SMI));
+ }
+ ///
+ /// Save SMI control register and try to disable all SMIs indivitually.
+ ///
+ SavedSmiControl = IoRead32 ((UINTN) GlobalSmiControlIoAddr);
+ ///
+ /// We can not disable Global SMI since it should be locked after SCHECK. we can only disable SMI sources indivitually.
+ /// Call to TxtDxeOemDisableSmi() for platform specific SMIs.
+ ///
+ Status = TxtDxeOemDisableSmi (TxtDxeCtx, TRUE);
+ ASSERT_EFI_ERROR (Status);
+
+ IoWrite32 (
+ (UINTN) GlobalSmiControlIoAddr,
+ (UINT32) (SavedSmiControl & 0x01)
+ );
+ } else {
+ ///
+ /// We can not disable Global SMI since it should be locked after SCHECK. we can only disable SMI sources indivitually.
+ /// Restore original SMI setting after SCHECK
+ /// Call to TxtDxeOemDisableSmi() for platform specific SMIs.
+ ///
+ Status = TxtDxeOemDisableSmi (TxtDxeCtx, FALSE);
+ ASSERT_EFI_ERROR (Status);
+
+ IoWrite32 (
+ (UINTN) GlobalSmiControlIoAddr,
+ (UINT32) (SavedSmiControl)
+ );
+ ///
+ /// Restore IA32_THERMAL_INTERRUPT MSR
+ ///
+ AsmWriteMsr64 (
+ (UINT32) IA32_THERM_INTERRUPT,
+ (UINT64) SavedIa32ThermInterruptMSR
+ );
+ if (x2ApicEnabled) {
+ AsmWriteMsr64 (MSR_EXT_XAPIC_LVT_THERM, SavedApicThermalValue);
+ } else {
+ *(UINT32 *) (UINTN) (LocalApicBaseAddr + LOCAL_APIC_THERMAL_DEF) = (UINT32) SavedApicThermalValue;
+
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read policy protocol to reset AUX content
+
+ @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure
+
+ @retval EFI_SUCCESS - No error happend
+ @retval EFI_NOT_FOUND - TxtPolicyProtocol is not found
+**/
+EFI_STATUS
+ResetTpmAux (
+ IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ ///
+ /// Check if TxtPolicy protocol installed
+ ///
+ if (TxtDxeCtx->CpuPlatformPolicy == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ ///
+ ///
+ ///
+ if (TxtDxeCtx->CpuPlatformPolicy->SecurityConfig->TxtFunctionConfig->ResetAux == 1) {
+ DEBUG ((EFI_D_INFO, "TXTDXE: Reset AUX content\n"));
+ Status = TxtDxeLibLaunchBiosAcm (TxtDxeCtx, TXT_RESET_AUX);
+ }
+
+ return Status;
+}
diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxeLib.h b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxeLib.h
new file mode 100644
index 0000000..573a06a
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxeLib.h
@@ -0,0 +1,289 @@
+/** @file
+ This file contains function definitions that can determine
+ the TXT capabilities of a platform during DXE and perform
+ certain specific platform tasks that are required for TXT
+ during DXE.
+
+@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 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
+
+**/
+#ifndef _TXT_DXE_LIB_H_
+#define _TXT_DXE_LIB_H_
+
+#include EFI_PROTOCOL_DEFINITION (MpService)
+#include "CpuAccess.h"
+
+#include EFI_PROTOCOL_DEFINITION (BootScriptSave)
+#include EFI_PROTOCOL_DEFINITION (CpuIo)
+#include EFI_GUID_DEFINITION (TxtInfoHob)
+#include EFI_PROTOCOL_DEFINITION (CpuPlatformPolicy)
+
+///
+/// The following switch is used in EfiScriptLib.h file. If enabled -
+/// forces linking to EfiScriptLib library
+///
+#define BASE_ADDR_MASK 0xFFFFF000
+#define TEST_PATTERN 0x5A5A5A5A5A5A5A5A
+#define MP_TIMEOUT_FOR_STARTUP_ALL_APS 0 ///< Set 0 for BSP always wait for APs
+
+///
+/// Chispet register
+///
+#define TXT_OPT_IN_VMX_AND_SMX_MSR_VALUE 0xFF03
+
+#define IA32_MTRR_PHYSBASE0 0x200
+#define IA32_MTRR_PHYSMASK9 0x213
+
+#define LOCAL_APIC_THERMAL_DEF 0x330
+ #define B_INTERRUPT_MASK (1 << 16)
+ #define B_DELIVERY_MODE (0x07 << 8)
+ #define V_MODE_SMI (0x02 << 8)
+ #define B_VECTOR (0xFF << 0)
+
+#pragma pack(push, 1)
+typedef struct _TXT_DXE_LIB_CONTEXT_ {
+ EFI_HANDLE ImageHandle;
+ EFI_SYSTEM_TABLE *SystemTable;
+ EFI_CPU_IO_PROTOCOL *CpuIo;
+ EFI_MP_SERVICES_PROTOCOL *MpService;
+
+ UINTN CpuCount;
+ TXT_INFO_DATA *TxtInfoData;
+ DXE_CPU_PLATFORM_POLICY_PROTOCOL *CpuPlatformPolicy;
+} TXT_DXE_LIB_CONTEXT;
+#pragma pack(pop)
+
+/**
+ This routine initializes and collects all Protocols and data required
+ by the routines in this file.
+
+ @param[in] ImageHandle - A pointer to the Image Handle for this file.
+ @param[in] SystemTable - A pointer to the EFI System Table
+ @param[in] TxtDxeCtx - A pointer to a caller allocated data structure that contains
+ all of the Protocols and data required by the routines
+ in this file.
+
+ @retval EFI_SUCCESS - Return EFI_SUCCESS if no error happen
+ @retval EFI_UNLOAD_IMAGE - If TxtInfoHob is not found
+**/
+EFI_STATUS
+InitializeTxtDxeLib (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable,
+ IN OUT TXT_DXE_LIB_CONTEXT *TxtDxeCtx
+ );
+/**
+ Determines whether or not the current processor is TXT Capable.
+
+ @retval TRUE - If the current processor supports TXT
+ @retval FALSE - If the current processor does not support TXT
+**/
+BOOLEAN
+IsTxtProcessor (
+ VOID
+ );
+/**
+ Determines whether or not the platform has executed an TXT launch by
+ examining the TPM Establishment bit.
+
+ @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure
+
+ @retval TRUE - If the TPM establishment bit is asserted.
+ @retval FALSE - If the TPM establishment bit is unasserted.
+**/
+BOOLEAN
+IsTxtEstablished (
+ IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx
+ );
+
+/**
+ Determines whether or not the platform has executed an TXT launch by
+ examining the TPM Establishment bit.
+
+ @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure
+
+ @retval TRUE - If the TPM establishment bit is asserted.
+ @retval FALSE - If the TPM establishment bit is unasserted.
+**/
+BOOLEAN
+IsTxtResetSet (
+ IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx
+ );
+/**
+ Determines whether or not the platform requires initialization for TXT use.
+
+ @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure
+
+ @retval TRUE - If the the platoform should be configured for TXT.
+ @retval FALSE - If TXT is not to be used.
+**/
+BOOLEAN
+IsTxtEnabled (
+ IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx
+ );
+/**
+ Adds and allocates architecturally defined TXT Configuration Space memory
+ region to GCD.
+
+ @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure
+
+ @retval EFI_SUCCESS - Always.
+**/
+EFI_STATUS
+ReserveTxtConfigSpace (
+ IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx
+ );
+/**
+ Allocates 1 MB of 1MB-aligned memory for use as TXT Device Memory. Records
+ the location of TXT Device Memory in TXT Chipset registers and then adds
+ programming instructions for these registers into BootScript.
+
+ @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure
+
+ @retval EFI_SUCCESS - TXT Device memory has been successfully initialized.
+ @retval EFI_ERROR - TXT Device memory not awailable.
+**/
+EFI_STATUS
+SetupTxtDeviceMemory (
+ IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx
+ );
+/**
+ Invokes TxtDxeLibLaunchBiosAcm to execute the SCHECK function.
+
+ @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure
+
+ @retval EFI_SUCCESS - Always.
+**/
+EFI_STATUS
+DoScheck (
+ IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx
+ );
+/**
+ Invokes TxtDxeLibLaunchBiosAcm to reset the TPM's establishment bit.
+
+ @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure
+
+ @retval EFI_SUCCESS - Always.
+**/
+EFI_STATUS
+ResetTpmEstBit (
+ IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx
+ );
+/**
+ Sets up the system and then launches the TXT BIOS ACM to run the function
+ requested by AcmFunction.
+
+ @param[in] AcmBase - Base address of BIOS ACM location
+ @param[in] Funct - Function number of BIOS ACM to be executed
+
+ @retval EFI_SUCCESS - Always.
+**/
+VOID
+LaunchBiosAcm (
+ IN UINT64 AcmBase,
+ IN UINT64 Funct
+ );
+
+/**
+ Sets up the system and then launches the TXT BIOS ACM to run the function
+ requested by AcmFunction.
+
+ @param[in] AcmFunction - Constant that represents the function from the BIOS ACM
+ that should be executed.
+ @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure
+
+ @retval EFI_SUCCESS - Always.
+**/
+EFI_STATUS
+TxtDxeLibLaunchBiosAcm (
+ IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx,
+ IN UINT64 AcmFunction
+ );
+/**
+ AP initial routine executed through MP service for TXT SCHECK
+**/
+VOID
+DoApInit (
+ VOID
+ );
+
+/**
+ Save AP configuration routine executed through MP service for TXT SCHECK
+**/
+VOID
+ApSaveConfig (
+ VOID
+ );
+
+/**
+ Restore AP configuration routine executed through MP service for TXT SCHECK
+**/
+VOID
+ApRestoreConfig (
+ VOID
+ );
+
+/**
+ Disable or restore possible SMI sources before or after POST SCHECK
+
+ @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure
+ @param[in] Operation - Boolean value telling what operation is requested:
+ TRUE - to save and then disable possible SMI sources
+ FALSE - to restore original SMI settings
+
+ @retval EFI_SUCCESS - always return EFI_SUCCESS
+**/
+EFI_STATUS
+DisableSmiSources (
+ IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx,
+ IN BOOLEAN Operation
+ );
+
+/**
+ This function gets called before/after run the SCHECK function, intend to avoid platform specific SMIs to interfere in BIOS POST
+ if BIOS SMM MP services or synchonization code is not well considered that some of APs are not waken up from Wait-for-SIPI state.
+ Function should preserve original SMI enabling setting in augument is TRUE, and then restore it in augurment is FALSE.
+ The caller is DisableSmiSources() in TxtDxeLib.c
+
+ @param[in] Operation = TRUE - Calling before SCHECK to saved and disable platform specific SMIs setting
+ = FALSE - Calling after SCHECK to restore platform specific SMIs setting
+
+ @retval EFI_SUCCESS - Always.
+**/
+extern
+EFI_STATUS
+EFIAPI
+TxtDxeOemDisableSmi (
+ IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx,
+ IN BOOLEAN Operation
+ );
+
+/**
+ Read policy protocol to reset AUX content
+
+ @param[in] TxtDxeCtx - A pointer to an initialized TXT DXE Context data structure
+
+ @retval EFI_SUCCESS - No error happend
+ @retval EFI_NOT_FOUND - TxtPolicyProtocol is not found
+**/
+EFI_STATUS
+ResetTpmAux (
+ IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx
+ );
+
+#endif
diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxeOem.c b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxeOem.c
new file mode 100644
index 0000000..bed83ec
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/TxtDxeOem.c
@@ -0,0 +1,78 @@
+/** @file
+ This file contain OEM/Platform implementation for TXT in DXE phase. It represents an abstract outline of the
+ steps required during DXE for enabling TXT. Each individual step is further
+ abstracted behind a function call interface. This is intended to minimize
+ the need to modify this file when porting TXT to future platforms.
+
+@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
+**/
+
+///
+/// External include files do NOT need to be explicitly specified in real EDKII
+/// environment
+///
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "Txt.h"
+#include "TxtDxeLib.h"
+#endif
+
+/**
+ This function gets called before/after run the SCHECK function, intend to avoid platform specific SMIs to interfere in BIOS POST
+ if BIOS SMM MP services or synchonization code is not well considered that some of APs are not waken up from Wait-for-SIPI state.
+ Function should preserve original SMI enabling setting in augument is TRUE, and then restore it in augurment is FALSE.
+ The caller is DisableSmiSources() in TxtDxeLib.c
+
+ @param[in] TxtDxeCtx - Point to TXT_DXE_LIB_CONTEXT structure
+ @param[in] Operation = TRUE - Calling before SCHECK to saved and disable platform specific SMIs setting
+ = FALSE - Calling after SCHECK to restore platform specific SMIs setting
+
+ @retval EFI_SUCCESS - Always.
+
+ **/
+EFI_STATUS
+EFIAPI
+TxtDxeOemDisableSmi (
+ IN TXT_DXE_LIB_CONTEXT *TxtDxeCtx,
+ IN BOOLEAN Operation
+ )
+{
+ static UINT16 SavedSmiControlDev29;
+ static UINT16 SavedSmiControlDev26;
+
+ if (Operation == TRUE) {
+ ///
+ /// Save and disable OEM/Platform specific SMIs
+ ///
+ /// Disable EHCI SMIs before giving control to TXT ACM. EHCI controller generating SMI during TXT ACM results in USB kbd issue
+ ///
+ SavedSmiControlDev26 = MmioRead16 (MmPciAddress (0, 0, 0, 0x1A, 0x6C));
+ SavedSmiControlDev29 = MmioRead16 (MmPciAddress (0, 0, 0, 0x1D, 0x6C));
+
+ MmioWrite16 (MmPciAddress (0, 0, 0, 0x1A, 0x6C), 0);
+ MmioWrite16 (MmPciAddress (0, 0, 0, 0x1D, 0x6C), 0);
+ } else {
+ ///
+ /// Restore or re-enable OEM/Platform specific SMIs
+ ///
+ /// Enable EHCI SMIs before giving control to TXT ACM.
+ ///
+ MmioWrite16 (MmPciAddress (0, 0, 0, 0x1A, 0x6C), SavedSmiControlDev26);
+ MmioWrite16 (MmPciAddress (0, 0, 0, 0x1D, 0x6C), SavedSmiControlDev29);
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/Mmx64.inc b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/Mmx64.inc
new file mode 100644
index 0000000..027e32e
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/Mmx64.inc
@@ -0,0 +1,494 @@
+;@file
+; This file contains macros supporting 64 bit assembly
+;
+;@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 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
+;
+
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Macro: _movq
+;
+; Input: rxx - general perpose 64 bit register
+; mmx - MMX register
+;
+; Output: None
+;
+; Registers:
+;
+; Description: Performs "movq rxx, mmx" and "movq mmx, rxx" operations
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+
+_movq MACRO toReg:REQ, frReg:REQ
+ LOCAL gReg, mReg, op
+ db 48h ; ; REX.W prefix
+IFIDNI <toReg>, <rax>
+ gReg = 00h
+ op = 7Eh
+ELSEIFIDNI <toReg>, <rcx>
+ gReg = 01h
+ op = 7Eh
+ELSEIFIDNI <toReg>, <rdx>
+ gReg = 02h
+ op = 7Eh
+ELSEIFIDNI <toReg>, <rbx>
+ gReg = 03h
+ op = 7Eh
+ELSEIFIDNI <toReg>, <rsp>
+ gReg = 04h
+ op = 7Eh
+ELSEIFIDNI <toReg>, <rbp>
+ gReg = 05h
+ op = 7Eh
+ELSEIFIDNI <toReg>, <rsi>
+ gReg = 06h
+ op = 7Eh
+ELSEIFIDNI <toReg>, <rdi>
+ gReg = 07h
+ op = 7Eh
+ELSEIFIDNI <toReg>, <mm0>
+ mReg = 0C0h + 0 * 08h
+ op = 6Eh
+ELSEIFIDNI <toReg>, <mm1>
+ mReg = 0C0h + 1 * 08h
+ op = 6Eh
+ELSEIFIDNI <toReg>, <mm2>
+ mReg = 0C0h + 2 * 08h
+ op = 6Eh
+ELSEIFIDNI <toReg>, <mm3>
+ mReg = 0C0h + 3 * 08h
+ op = 6Eh
+ELSEIFIDNI <toReg>, <mm4>
+ mReg = 0C0h + 4 * 08h
+ op = 6Eh
+ELSEIFIDNI <toReg>, <mm5>
+ mReg = 0C0h + 5 * 08h
+ op = 6Eh
+ELSEIFIDNI <toReg>, <mm6>
+ mReg = 0C0h + 6 * 08h
+ op = 6Eh
+ELSEIFIDNI <toReg>, <mm7>
+ mReg = 0C0h + 7 * 08h
+ op = 6Eh
+ENDIF
+
+;; If op = 7E format movq rxx, mmx
+
+IFIDNI <frReg>, <rax>
+ gReg = 00h
+ IF op EQ 7Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <rcx>
+ gReg = 01h
+ IF op EQ 7Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <rdx>
+ gReg = 02h
+ IF op EQ 7Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <rbx>
+ gReg = 03h
+ IF op EQ 7Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <rsp>
+ gReg = 04h
+ IF op EQ 7Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <rbp>
+ gReg = 05h
+ IF op EQ 7Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <rsi>
+ gReg = 06h
+ IF op EQ 7Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <rdi>
+ gReg = 07h
+ IF op EQ 7Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <mm0>
+ mReg = 0C0h + 0 * 08h
+ IF op EQ 6Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <mm1>
+ mReg = 0C0h + 1 * 08h
+ IF op EQ 6Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <mm2>
+ mReg = 0C0h + 2 * 08h
+ IF op EQ 6Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <mm3>
+ mReg = 0C0h + 3 * 08h
+ IF op EQ 6Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <mm4>
+ mReg = 0C0h + 4 * 08h
+ IF op EQ 6Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <mm5>
+ mReg = 0C0h + 5 * 08h
+ IF op EQ 6Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <mm6>
+ mReg = 0C0h + 6 * 08h
+ IF op EQ 6Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <mm7>
+ mReg = 0C0h + 7 * 08h
+ IF op EQ 6Eh
+ .ERR
+ ENDIF
+ENDIF
+ db 0Fh, op, gReg + mReg
+ENDM
+
+
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Macro: _movd
+;
+; Input: exx - general perpose 32 bit register
+; mmx - MMX register
+;
+; Output: None
+;
+; Registers:
+;
+; Description: Performs "movd exx, mmx" and "movd mmx, exx" operations
+; coded to perform in compatibility or protected mode but
+; assembled by ml64
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+
+
+_movd MACRO toReg:REQ, frReg:REQ
+ LOCAL gReg, mReg, op
+IFIDNI <toReg>, <eax>
+ gReg = 00h
+ op = 7Eh
+ELSEIFIDNI <toReg>, <ecx>
+ gReg = 01h
+ op = 7Eh
+ELSEIFIDNI <toReg>, <edx>
+ gReg = 02h
+ op = 7Eh
+ELSEIFIDNI <toReg>, <ebx>
+ gReg = 03h
+ op = 7Eh
+ELSEIFIDNI <toReg>, <esp>
+ gReg = 04h
+ op = 7Eh
+ELSEIFIDNI <toReg>, <ebp>
+ gReg = 05h
+ op = 7Eh
+ELSEIFIDNI <toReg>, <esi>
+ gReg = 06h
+ op = 7Eh
+ELSEIFIDNI <toReg>, <edi>
+ gReg = 07h
+ op = 7Eh
+ELSEIFIDNI <toReg>, <mm0>
+ mReg = 0C0h + 0 * 08h
+ op = 6Eh
+ELSEIFIDNI <toReg>, <mm1>
+ mReg = 0C0h + 1 * 08h
+ op = 6Eh
+ELSEIFIDNI <toReg>, <mm2>
+ mReg = 0C0h + 2 * 08h
+ op = 6Eh
+ELSEIFIDNI <toReg>, <mm3>
+ mReg = 0C0h + 3 * 08h
+ op = 6Eh
+ELSEIFIDNI <toReg>, <mm4>
+ mReg = 0C0h + 4 * 08h
+ op = 6Eh
+ELSEIFIDNI <toReg>, <mm5>
+ mReg = 0C0h + 5 * 08h
+ op = 6Eh
+ELSEIFIDNI <toReg>, <mm6>
+ mReg = 0C0h + 6 * 08h
+ op = 6Eh
+ELSEIFIDNI <toReg>, <mm7>
+ mReg = 0C0h + 7 * 08h
+ op = 6Eh
+ENDIF
+
+;; If op = 7E format movq exx, mmx
+
+IFIDNI <frReg>, <eax>
+ gReg = 00h
+ IF op EQ 7Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <ecx>
+ gReg = 01h
+ IF op EQ 7Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <edx>
+ gReg = 02h
+ IF op EQ 7Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <ebx>
+ gReg = 03h
+ IF op EQ 7Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <esp>
+ gReg = 04h
+ IF op EQ 7Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <ebp>
+ gReg = 05h
+ IF op EQ 7Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <esi>
+ gReg = 06h
+ IF op EQ 7Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <edi>
+ gReg = 07h
+ IF op EQ 7Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <mm0>
+ mReg = 0C0h + 0 * 08h
+ IF op EQ 6Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <mm1>
+ mReg = 0C0h + 1 * 08h
+ IF op EQ 6Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <mm2>
+ mReg = 0C0h + 2 * 08h
+ IF op EQ 6Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <mm3>
+ mReg = 0C0h + 3 * 08h
+ IF op EQ 6Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <mm4>
+ mReg = 0C0h + 4 * 08h
+ IF op EQ 6Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <mm5>
+ mReg = 0C0h + 5 * 08h
+ IF op EQ 6Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <mm6>
+ mReg = 0C0h + 6 * 08h
+ IF op EQ 6Eh
+ .ERR
+ ENDIF
+ELSEIFIDNI <frReg>, <mm7>
+ mReg = 0C0h + 7 * 08h
+ IF op EQ 6Eh
+ .ERR
+ ENDIF
+ENDIF
+ db 0Fh, op, gReg + mReg
+ENDM
+
+;-----------------------------------------------------------------------------
+; 64 bit macros
+;
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Macro: PUSHA_64
+;
+; Input: None
+;
+; Output: None
+;
+; Registers:
+;
+; Description: Saves all registers on stack
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+PUSHA_64 MACRO
+ push rsp
+ push rbp
+ push rax
+ push rbx
+ push rcx
+ push rdx
+ push rsi
+ push rdi
+ push r8
+ push r9
+ push r10
+ push r11
+ push r12
+ push r13
+ push r14
+ push r15
+ENDM
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Macro: POPA_64
+;
+; Input: None
+;
+; Output: None
+;
+; Registers:
+;
+; Description: Restores all registers from stack
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+
+POPA_64 MACRO
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ pop r11
+ pop r10
+ pop r9
+ pop r8
+ pop rdi
+ pop rsi
+ pop rdx
+ pop rcx
+ pop rbx
+ pop rax
+ pop rbp
+ pop rsp
+ENDM
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Macro: START_FRAME
+;
+; Input: None
+;
+; Output: None
+;
+; Registers:
+;
+; Description: Starts frame declaration. Creates variable to hold total
+; size of all local vars.
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+
+START_FRAME MACRO
+ SZ = 0
+ENDM
+
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Macro: MAKE_LOCAL
+;
+; Input: ARG - var definition in form Label[Count]:QuolifiedType
+;
+; Output: None
+;
+; Registers:
+;
+; Description: Defines local procedure variable. Adds size of created variable
+; to total size of locals.
+; size of all local vars.
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+
+MAKE_LOCAL MACRO ARG:REQ
+ LOCAL brk, rbrk, clm, lbl, cnt, qtp
+ brk INSTR <ARG>, <[>
+ rbrk INSTR <ARG>, <]>
+ clm INSTR <ARG>, <:>
+ IF brk GT 0
+ lbl SUBSTR <ARG>, 1, brk-1
+ cnt SUBSTR <ARG>, brk+1, rbrk-brk-1
+ qtp SUBSTR <ARG>, clm+1
+ LOCAL lbl[cnt]:qtp
+ ELSE
+ lbl SUBSTR <ARG>, 1, clm-1
+ qtp SUBSTR <ARG>, clm+1
+ LOCAL lbl:qtp
+ ENDIF
+
+ SZ = SZ + sizeof lbl
+ENDM
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Macro: END_FRAME
+;
+; Input: None
+;
+; Output: None
+;
+; Registers:
+;
+; Description: Ends frame declaration. Creates stack sufficient to hold
+; all declared variables.
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+
+END_FRAME MACRO
+ SZ = SZ + 10h ; Margin
+ enter SZ, 0 ; With spare room on stack
+ .allocstack SZ
+ .endprolog
+ENDM
+
+
+
+SAVED_GDT TEXTEQU <mm0>
+SAVED_SS TEXTEQU <mm1>
+SAVED_ESP TEXTEQU <mm2>
+SAVED_EBP TEXTEQU <mm3>
+ \ No newline at end of file
diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/TxtDxeAp.asm b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/TxtDxeAp.asm
new file mode 100644
index 0000000..f1c44b9
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/TxtDxeAp.asm
@@ -0,0 +1,364 @@
+;/*++
+; 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
+;--*/
+;
+;/*++
+;
+; Copyright (c) 1999 - 2011 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:
+;
+; TxtDxeAp.asm
+;
+; Abstract:
+;
+; This file contains DXE AP initialization code.
+;
+;--*/
+
+ .xlist
+ include txt.inc
+ include mmx64.inc
+ .list
+
+
+ _TEXT SEGMENT
+
+
+EXTERN mAcmBase:QWORD
+EXTERN mMcuAddr:QWORD
+EXTERN mApMtrrTab:QWORD
+EXTERN mApIdt:QWORD
+EXTERN mApCr4:QWORD
+EXTERN mApSavedIa32ThermInterruptMSR:QWORD
+EXTERN mApSavedApicThermalValue:DWORD
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: DoApInit
+;
+; Input: AcmBase - Base address of LT BIOS ACM
+; McuAddr - Address of MCU patch in flash
+;
+; Output: None
+;
+; Registers: All are preserved
+;
+; Description: Initiatialize AP before GETSEC as per TXT BWG
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+
+DoApInit PROC FRAME
+
+ START_FRAME
+ MAKE_LOCAL ACM_SIZE_TO_CACHE:QWORD
+ MAKE_LOCAL ACM_BASE_TO_CACHE:QWORD
+ MAKE_LOCAL NEXT_MTRR_INDEX:QWORD
+ MAKE_LOCAL NEXT_MTRR_SIZE:QWORD
+ ; jmp $
+ END_FRAME
+
+ pushf
+ cli
+ PUSHA_64
+ ;
+ ; Check uCode was loaded or not
+ ;
+ mov rcx, MCU_REV_MSR
+ xor rax, rax
+ xor rdx, rdx
+ wrmsr
+ mov rax, 1
+ cpuid
+ mov rcx, MCU_REV_MSR
+ rdmsr
+ or rdx, rdx
+ jnz uCode_loaded
+
+ ;
+ ; Load uCode update
+ ;
+ mov rax, 1
+ cpuid
+
+ mov rax, mMcuAddr
+ lea rax, [rax + SIZEOF MCU] ; RAX -> MCU data (after header)
+ xor rdx, rdx
+ mov rcx, MCU_LOAD_MSR ; Trigger to load MCU
+
+ wrmsr ; Load MCU
+
+ mov rax, 1
+ cpuid
+uCode_loaded:
+;-----------------------------------------------------------------------------
+;
+; Section: Initial RLPs cache requirements
+;
+; Description: Ensure CR0.CD and CR0.NW are cleared
+;
+;-----------------------------------------------------------------------------
+ ;
+ ; Clear CR0.CD and CR0.NW
+ ;
+ mov rax, cr0
+ and rax, NOT (CR0_CD_MASK + CR0_NW_MASK)
+ mov cr0, rax
+
+;-----------------------------------------------------------------------------
+;
+; Section: Clean all MCi_STATUS MSR registers
+;
+; Description: MCA registers are cleaned
+;
+;-----------------------------------------------------------------------------
+
+ mov rcx, MCG_CAP
+ rdmsr
+ movzx rbx, al ; ebx = MCR bank count
+ xor rax, rax ; Write 0 into all MCi_STATUS registers
+ xor rdx, rdx
+ mov rcx, MC0_STATUS
+
+McaErrorCleanLoopStart:
+ wrmsr
+ dec rbx
+ jz @F
+ add rcx, 4 ; ecx = number of MSRs per bank
+ jmp McaErrorCleanLoopStart
+
+@@:
+
+ mov rcx,IA32_APIC_BASE
+ rdmsr
+ and rax,BIT11+BIT10
+ cmp rax,BIT11+BIT10
+ jne x2ApicDisabled
+ mov rcx,EFI_MSR_EXT_XAPIC_LVT_THERM
+ rdmsr
+ and eax, NOT (B_INTERRUPT_MASK + B_DELIVERY_MODE + B_VECTOR)
+ or eax, (B_INTERRUPT_MASK + V_MODE_SMI)
+ wrmsr
+ jmp @f
+x2ApicDisabled:
+ ; mask thermal LVT
+ mov rcx, IA32_APIC_BASE
+ rdmsr ; Get APIC Base
+ and rax, BASE_ADDR_MASK ; Just need the address
+ mov edx, [rax+LOCAL_APIC_THERMAL_DEF]
+ and edx, NOT (B_INTERRUPT_MASK + B_DELIVERY_MODE + B_VECTOR)
+ or edx, (B_INTERRUPT_MASK + V_MODE_SMI)
+ mov DWORD PTR [rax+LOCAL_APIC_THERMAL_DEF], edx ;disable DTS SMIs
+@@:
+ POPA_64
+ popf
+
+ leave
+ ret 0
+DoApInit ENDP
+
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: ApSaveConfig
+;
+; Input: None
+;
+; Output: None
+;
+; Registers: All are preserved
+;
+; Description: Saves AP configuration
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+ApSaveConfig PROC FRAME
+ START_FRAME
+ END_FRAME
+
+ pushf
+ cli
+ PUSHA_64
+
+ mov rcx, IA32_MTRR_CAP
+ rdmsr
+ and rax, 0FFh
+ shl rax, 1
+ mov rcx, rax
+
+ lea rbx, mApMtrrTab
+
+SaveNextMtrr:
+ add rcx, IA32_MTRR_PHYSBASE0 - 1
+ rdmsr
+ mov QWORD PTR [rbx+0], rax
+ mov QWORD PTR [rbx+8], rdx
+ sub rcx, IA32_MTRR_PHYSBASE0 - 1
+ add rbx, 10h
+ loop SaveNextMtrr
+
+ mov rcx, IA32_MTRR_DEF_TYPE
+ rdmsr
+ mov QWORD PTR [rbx+0], rax
+ mov QWORD PTR [rbx+8], rdx
+
+ lea rbx, mApIdt
+ sidt [rbx]
+ lea rbx, mApCr4
+ mov rax, cr4
+ mov QWORD PTR [rbx], rax
+
+ mov rcx,IA32_APIC_BASE
+ rdmsr
+ and rax,BIT11+BIT10
+ cmp rax,BIT11+BIT10
+ jne x2ApicDisabled
+ mov rcx,EFI_MSR_EXT_XAPIC_LVT_THERM
+ rdmsr
+ lea rbx, mApSavedApicThermalValue
+ mov DWORD PTR [rbx], eax ; read and save thermal LVT
+ jmp @f
+x2ApicDisabled:
+
+ mov rcx, IA32_APIC_BASE
+ rdmsr ; Get APIC Base
+ and rax, BASE_ADDR_MASK ; Just need the address
+ lea rbx, mApSavedApicThermalValue
+ mov edx, DWORD PTR [rax+LOCAL_APIC_THERMAL_DEF]
+ mov DWORD PTR [rbx], edx ; read and save thermal LVT
+@@:
+ mov rcx, EFI_MSR_IA32_THERM_INTERRUPT
+ rdmsr ;
+ lea rbx, mApSavedIa32ThermInterruptMSR
+ mov QWORD PTR [rbx+0], rax
+ mov QWORD PTR [rbx+8], rdx
+ ;disable THERMAL INT
+ and rax, NOT (BIT0+BIT1+BIT2+BIT4+BIT15+BIT23)
+ wrmsr
+
+ wbinvd
+
+ POPA_64
+ popf
+
+ leave
+ ret 0
+ApSaveConfig ENDP
+
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: ApRestoreConfig
+;
+; Input: None
+;
+; Output: None
+;
+; Registers: All are preserved
+;
+; Description: Saves AP configuration
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+ApRestoreConfig PROC FRAME
+ START_FRAME
+ END_FRAME
+
+ pushf
+ cli
+ PUSHA_64
+
+ ;
+ ; Disable cache
+ ;
+ mov rax, cr0 ; set CR0:CD and CR0:NE, clear CR0:NW
+ or rax, CR0_CD_MASK OR CR0_NE_MASK
+ and rax, NOT CR0_NW_MASK
+ mov cr0, rax
+ wbinvd
+
+ mov rcx, IA32_MTRR_CAP
+ rdmsr
+ and rax, 0FFh
+ shl rax, 1
+ mov rcx, rax
+
+ lea rbx, mApMtrrTab
+
+RestoreNextMtrr:
+ add rcx, IA32_MTRR_PHYSBASE0 - 1
+ mov rax, QWORD PTR [rbx+0]
+ mov rdx, QWORD PTR [rbx+8]
+ wrmsr
+ sub rcx, IA32_MTRR_PHYSBASE0 - 1
+ add rbx, 10h
+ loop RestoreNextMtrr
+
+ mov rax, QWORD PTR [rbx+0]
+ mov rdx, QWORD PTR [rbx+8]
+ mov rcx, IA32_MTRR_DEF_TYPE
+ wrmsr
+
+ lea rbx, mApIdt
+ lidt FWORD PTR [rbx]
+ lea rbx, mApCr4
+ mov rax, QWORD PTR [rbx]
+ mov cr4, rax
+
+ mov rcx, EFI_MSR_IA32_THERM_INTERRUPT
+ lea rbx, mApSavedIa32ThermInterruptMSR
+ mov rax, QWORD PTR [rbx+0]
+ mov rdx, QWORD PTR [rbx+8]
+ wrmsr
+
+ mov rcx,IA32_APIC_BASE
+ rdmsr
+ and rax,BIT11+BIT10
+ cmp rax,BIT11+BIT10
+ jne x2ApicDisabled
+ mov rcx,EFI_MSR_EXT_XAPIC_LVT_THERM
+ lea rbx, mApSavedApicThermalValue
+ mov eax,DWORD PTR [rbx] ;restore thermal LVT
+ xor rdx,rdx
+ wrmsr
+ jmp @f
+x2ApicDisabled:
+
+ mov rcx, IA32_APIC_BASE
+ rdmsr ; Get APIC Base
+ and rax, BASE_ADDR_MASK ; Just need the address
+ lea rbx, mApSavedApicThermalValue
+ mov edx, DWORD PTR [rbx]
+ mov DWORD PTR [rax+LOCAL_APIC_THERMAL_DEF], edx ; restore thermal LVT
+@@:
+ ;
+ ; Enable cache
+ ;
+ mov rax, cr0
+ and rax, NOT CR0_CD_MASK
+ mov cr0, rax
+
+ POPA_64
+ popf
+
+ leave
+ ret 0
+ApRestoreConfig ENDP
+
+_TEXT ENDS
+
+ END
diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/TxtDxeBsp.asm b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/TxtDxeBsp.asm
new file mode 100644
index 0000000..00f9c87
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/TxtInit/Dxe/x64/TxtDxeBsp.asm
@@ -0,0 +1,712 @@
+;/*++
+; 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
+;--*/
+;
+;/*++
+;
+; Copyright (c) 1999 - 2011 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:
+;
+; TxtDxeBsp.asm
+;
+; Abstract:
+;
+; This file contains code to launch BIOS ACM functions in DXE phase
+;
+;--*/
+ .xlist
+ include txt.inc
+ include mmx64.inc
+ .list
+
+
+ _TEXT SEGMENT
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: LaunchBiosAcm
+;
+; Input: AcmBase - Base address of LT BIOS ACM
+; Function - function number to execute
+;
+; Output: None
+;
+; Registers: None are preserved
+;
+; Description: Setup GETSEC environment (protected mode, mtrrs, etc) and
+; invoke GETSEC:ENTERACCS with requested BIOS ACM entry point.
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+
+LaunchBiosAcm PROC FRAME
+
+ START_FRAME
+ MAKE_LOCAL AcmBase:QWORD
+ MAKE_LOCAL Funct:QWORD
+ MAKE_LOCAL BIOS_GDT[2]:QWORD
+ MAKE_LOCAL CompModeSel:QWORD
+ MAKE_LOCAL CompModeOff:QWORD
+ MAKE_LOCAL LongModeSel:QWORD
+ MAKE_LOCAL LongModeOff:QWORD
+ MAKE_LOCAL SavedCR3:QWORD
+ MAKE_LOCAL SavedCR4:QWORD
+ MAKE_LOCAL SavedDS:QWORD
+ MAKE_LOCAL SavedES:QWORD
+ MAKE_LOCAL SavedGS:QWORD
+ MAKE_LOCAL SavedFS:QWORD
+ MAKE_LOCAL SavedMiscEnablesRax:QWORD
+ MAKE_LOCAL SavedMiscEnablesRdx:QWORD
+ MAKE_LOCAL MtrrTab[2*(IA32_MTRR_PHYSMASK9 - IA32_MTRR_PHYSBASE0 + 1)]:QWORD
+ MAKE_LOCAL ACM_SIZE_TO_CACHE:QWORD
+ MAKE_LOCAL ACM_BASE_TO_CACHE:QWORD
+ MAKE_LOCAL NEXT_MTRR_INDEX:QWORD
+ MAKE_LOCAL NEXT_MTRR_SIZE:QWORD
+ MAKE_LOCAL MTRR_COUNT:QWORD
+ MAKE_LOCAL MtrrTypeRax:QWORD
+ MAKE_LOCAL MtrrTypeRdx:QWORD
+ END_FRAME
+
+ ;
+ ; Save input parameters
+ ;
+ mov AcmBase, rcx
+
+ mov Funct, rdx
+
+ sgdt BIOS_GDT ; save gdtr
+
+ ;
+ ; Save the general purpose register state
+ ;
+ pushf
+ cli
+
+ PUSHA_64
+ ;
+ ; Tell where we are
+ ;
+ in ax, 80h
+ mov ah, BYTE PTR Funct
+ or ah, PORT80_CODE_PREFIX
+ out 80h, ax
+ ;
+ ; Save segment registers.
+ ;
+ mov ax, ds
+ mov SavedDS, rax
+ mov ax, es
+ mov SavedES, rax
+ mov ax, gs
+ mov SavedGS, rax
+ mov ax, fs
+ mov SavedFS, rax
+
+ ; Save cr4
+ ;
+ mov rax, cr4
+ mov SavedCR4, rax
+
+ ;
+ ; Save IA32_MISC_ENABLES MSR
+ ;
+ mov rcx, IA32_MISC_ENABLE_MSR
+ rdmsr
+ mov SavedMiscEnablesRax, rax
+ mov SavedMiscEnablesRdx, rdx
+
+;-----------------------------------------------------------------------------
+;
+; Section: Save variable MTRRs
+;
+; Description: All variable MTRRs are saved in local variables.
+; They will be restored after runnong of BIOS ACM
+;
+;-----------------------------------------------------------------------------
+ mov rcx, IA32_MTRR_CAP
+ rdmsr
+ and rax, 0FFh
+ shl rax, 1
+ mov MTRR_COUNT, rax
+ mov rcx, rax
+ lea rbx, MtrrTab
+
+SaveNextMtrr:
+ add rcx, IA32_MTRR_PHYSBASE0 - 1
+ rdmsr
+ mov [rbx+0], rax
+ mov [rbx+8], rdx
+ sub rcx, IA32_MTRR_PHYSBASE0 - 1
+ add rbx, 10h
+ loop SaveNextMtrr
+
+ ;
+ ; Save IA32_MTRR_DEF_TYPE MSR
+ ;
+ mov rcx, IA32_MTRR_DEF_TYPE
+ rdmsr
+ mov MtrrTypeRax, rax
+ mov MtrrTypeRdx, rdx
+
+;-----------------------------------------------------------------------------
+;
+; Section: Program MTRRs
+;
+; Description: Variable MTRRs are programmed to cache ACM as WB
+;
+;-----------------------------------------------------------------------------
+ ;
+ ; Enable SMXE, SSE and debug extensions
+ ;
+ mov rax, cr4
+ or rax, CR4_OSFXSR + CR4_DE + CR4_SMXE
+ mov cr4, rax
+
+ ;
+ ; Disable cache
+ ;
+ mov rax, cr0 ; set CR0:CD and CR0:NE, clear CR0:NW
+ or rax, CR0_CD_MASK OR CR0_NE_MASK
+ and rax, NOT CR0_NW_MASK
+ mov cr0, rax
+ wbinvd
+ ;
+ ; Disable MTRRs, set Default Type to UC
+ ;
+ mov rcx, IA32_MTRR_DEF_TYPE
+ xor rax, rax
+ xor rdx, rdx
+ wrmsr
+
+ ;
+ ; Clear all of the Variable MTRRs
+ ;
+ mov rcx, MTRR_COUNT
+
+ClearNextMttr:
+ add rcx, IA32_MTRR_PHYSBASE0 - 1
+ wrmsr
+ sub rcx, IA32_MTRR_PHYSBASE0 - 1
+ loop ClearNextMttr
+
+ ;
+ ; Determine size of AC module
+ ;
+ mov rsi, AcmBase
+ xor rax, rax
+ mov eax, DWORD PTR [rsi+ACM_HEADER.AcmSize]
+ shl rax, 2 ; ...in bytes (ACM header has size in dwords)
+ ;
+ ; Round up to page size
+ ;
+ add rax, 0FFFh ;
+ and rax, 0FFFFF000h ; Aligned to a page (4KB)
+
+ ;
+ ; Program MTRRs to cover BIOS ACM
+ ;
+ sub rcx, rcx
+ mov NEXT_MTRR_INDEX, rcx ; Start from MTRR0
+
+ ;
+ ; Save remaining size to cache
+ ;
+ mov ACM_SIZE_TO_CACHE, rax ; Size of ACM that must be cached
+ mov ACM_BASE_TO_CACHE, rsi ; Base ACM address
+
+nextMtrr:
+ ;
+ ; Get remaining size to cache
+ ;
+ mov rax, ACM_SIZE_TO_CACHE
+ and rax, rax
+ jz done ; 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
+ ;
+ mov rsi, ACM_BASE_TO_CACHE
+ bsf rcx, rsi ; Get index of lowest bit set in base address
+ ;
+ ; Convert index into size to be cached by next MTRR
+ ;
+ mov rdx, 1h
+ shl rdx, cl ; Alignment is in rdx
+ cmp rdx, rax ; 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 rcx, rax ; Get index of highest set bit
+ ;
+ ; Convert index into size to be cached by next MTRR
+ ;
+ mov rdx, 1
+ shl rdx, cl ; Size to cache
+
+gotSize:
+ mov rax, rdx
+ mov NEXT_MTRR_SIZE, rax ; Save
+
+ ;
+ ; Compute MTRR mask value: Mask = NOT (Size - 1)
+ ;
+ dec rax ; eax - size to cache less one byte
+ not rax ; eax contains low 32 bits of mask
+ or rax, MTRR_VALID ; Set valid bit
+ ;
+ ; Program mask register
+ ;
+ mov rcx, IA32_MTRR_PHYSMASK0 ; setup variable mtrr
+ mov rbx, NEXT_MTRR_INDEX
+ add rcx, rbx
+
+ mov rdx, 0Fh
+ wrmsr
+ ;
+ ; Program base register
+ ;
+ sub rdx, rdx
+ mov rcx, IA32_MTRR_PHYSBASE0 ; setup variable mtrr
+ add rcx, rbx ; ebx is still NEXT_MTRR_INDEX
+
+ mov rax, ACM_BASE_TO_CACHE
+ or rax, WB ; set type to write back
+ wrmsr
+ ;
+ ; Advance and loop
+ ; Reduce remaining size to cache
+ ;
+ mov rbx, ACM_SIZE_TO_CACHE
+ mov rax, NEXT_MTRR_SIZE
+ sub rbx, rax
+ mov ACM_SIZE_TO_CACHE, rbx
+
+ ;
+ ; Increment MTRR index
+ ;
+ mov rbx, NEXT_MTRR_INDEX
+ add rbx, 2
+ mov NEXT_MTRR_INDEX, rbx
+ ;
+ ; Increment base address to cache
+ ;
+ mov rbx, ACM_BASE_TO_CACHE
+ mov rax, NEXT_MTRR_SIZE
+ add rbx, rax
+ mov ACM_BASE_TO_CACHE, rbx
+
+ jmp nextMtrr
+
+done:
+ ;
+ ; Enable Variable MTRRs
+ ;
+ xor rdx, rdx
+ mov rax, MTRR_ENABLE
+ mov rcx, IA32_MTRR_DEF_TYPE
+ wrmsr
+ ;
+ ; Enable cache
+ ;
+ mov rax, cr0
+ and rax, NOT CR0_CD_MASK
+ mov cr0, rax
+
+ ;
+ ; Clean all MCi_STATUS MSR registers
+ ; SCLEAN will generate GPF otherwise
+ ;
+ mov rcx, MCG_CAP
+ rdmsr
+ movzx rbx, al ; ebx = MCR bank count
+ xor rax, rax ; Write 0 into all MCi_STATUS registers
+ xor rdx, rdx
+ mov rcx, MC0_STATUS
+
+McaErrorCleanLoopStart:
+ wrmsr
+ dec rbx
+ jz @F
+ add rcx, 4 ; ecx = number of MSRs per bank
+ jmp McaErrorCleanLoopStart
+
+@@:
+;-----------------------------------------------------------------------------
+;
+; Section: Find Compatible Segment Descriptor in GDT
+;
+; Description: GDT is scanned until code descriptor with L bit = 0 is found
+;
+;-----------------------------------------------------------------------------
+
+ lea rax, BIOS_GDT
+ add rax, 2 ; Point to base
+ mov rax, [rax] ; Get base of GDT
+ mov rbx, rax ; Save GDT base
+
+ mov cx, WORD PTR BIOS_GDT
+ movzx rcx, cx
+ inc rcx ; rcx - total size of GDT in bytes
+ add rcx, rax ; rcx - end of GDT
+
+loopStart:
+ cmp QWORD PTR [rax], 0 ; Reserved?
+ je ApplicationDescriptor
+ test BYTE PTR [rax].SEG_DESCRIPTOR.AR0_7, MASK D_T
+ jz nextDescriptor ; JIf system descriptor
+ ;
+ ; Application descriptor found
+ ;
+ test BYTE PTR [rax].SEG_DESCRIPTOR.AR0_7, 8 ; Bit 3 of sType - code segment if set
+ jz nextDescriptor ; JIf data descriptor
+ ;
+ ; Code descriptor is found
+ ;
+ test byte ptr [rax].SEG_DESCRIPTOR.LAR16_23, MASK L
+ jnz nextDescriptor
+ ;
+ ; Compatibility mode code descriptor is found
+ ;
+ sub rax, rbx ; rax is compatibility segment selector
+ jmp CompatibilityModeJump
+
+nextDescriptor:
+ cmp rax, rcx
+ jb @F
+ jmp $ ; Nothing found - impossible situation
+
+@@:
+ test BYTE PTR [rax].SEG_DESCRIPTOR.AR0_7, MASK D_T
+ jz @F
+
+ApplicationDescriptor:
+ ;
+ ; Application descriptor - 8 bytes
+ ;
+ add rax, 8
+ jmp loopStart
+
+@@:
+ add rax, 16
+ jmp loopStart
+
+;-----------------------------------------------------------------------------
+;
+; Section: Jump to compatibility mode
+;
+; Description: Found selector and known label offset
+; are used to transfer control to compatibility mode.
+;
+; NOTE!
+; Code programmed from this point on till the return to long mode
+; looks differently than code actually executed by CPU
+; This is because assembler is in x64 mode whereas CPU is not.
+; Whereever differences are present between written and executed code,
+; actual instructions are shown in comments.
+;
+; Example1: Programmed: mov rax, cr4
+; Executed: mov eax, cr4
+; Assembler fails to assemble "mov eax, cr4" since CR4 is
+; 64 bits wide in x64 mode. Generated opcodes are nevertheless
+; correct.
+;
+; Example2: Programmed: mov eax, DWORD PTR [rbx+0]
+; Executed: mov eax, DWORD PTR [ebx+0]
+; Default addressing in x64 mode is 64 bit. If ebx were coded
+; in this example, assembler would generate unneeded REX prefix.
+; By programming rbx this prefix is not generated and
+; opcode corresponds to ebx addressing in compatibility mode
+;
+;-----------------------------------------------------------------------------
+
+CompatibilityModeJump:
+ ;
+ ; Save Long mode and Compatibility mode selectors and offsets before transition
+ ;
+ mov CompModeSel, rax ; Save Compatibility Mode selector
+ mov rcx, OFFSET ProtectedMode2
+ mov CompModeOff, rcx
+ mov cx, cs
+ movzx rcx, cx
+ mov LongModeSel, rcx
+ mov rcx, OFFSET LongMode2
+ mov LongModeOff, rcx
+
+ shl rax, 32
+ mov rcx, OFFSET CompatibilityMode
+ or rax, rcx
+ push rax
+ retf
+
+CompatibilityMode:
+;-----------------------------------------------------------------------------
+;
+; Section: Jump to protected mode
+;
+; Description: Compatibility mode is disabled since BIOS ACM must run
+; in protected 32 bit mode.
+;
+;-----------------------------------------------------------------------------
+
+ ;
+ ; Disable paging
+ ;
+ mov rcx, cr0
+ and ecx, DWORD PTR (NOT BIT31)
+ mov cr0, rcx
+ ;
+ ; Clear EFER.LME
+ ;
+ mov ecx, IA32_EFER_MSR
+ rdmsr
+ and eax, NOT LME
+ wrmsr
+ jmp ProtectedMode
+
+ProtectedMode:
+
+;-----------------------------------------------------------------------------
+;
+; Section: Launch BIOS ACM
+;
+; Description: Prepare and execute GETSEC[ENTERACCS]
+;
+;-----------------------------------------------------------------------------
+
+ ;
+ ; Save return values in MMX registers
+ ;
+
+ mov ax, ss
+ movzx eax,ax
+% _movd SAVED_SS, eax
+% _movd SAVED_EBP, ebp
+% _movd SAVED_ESP, esp
+ lea eax, BIOS_GDT
+% _movd SAVED_GDT, eax
+ mov rax, cr3 ; mov eax, cr3 - in 32 bit mode
+ mov DWORD PTR SavedCR3, eax
+ ;
+ ; Call GETSEC[ENTERACCS]
+ ;
+ mov esi, DWORD PTR Funct ; esi = ACM function
+ mov eax, DWORD PTR AcmBase
+ mov ebx, eax ; ebx = AcmBase
+ mov ecx, DWORD PTR [rbx+ACM_HEADER.AcmSize] ; mov DWORD PTR [ebx+ACM_HEADER.AcmSize] - in 32 bit mode
+ ; ecx = size of ACM in dwords
+ shl ecx, 2 ; ecx = size of ACM in bytes
+ xor edx, edx
+ xor edi, edi
+ mov eax, ENTERACCS ; eax = ENTERACCS
+
+ _GETSEC
+
+;for debugging only
+; mov ax, 055AAh
+; out 80h, ax
+;; jmp $
+;-----------------------------------------------------------------------------
+;
+; Section: Restore protected mode environment
+;
+; Description: Since BIOS ACM changes GDT,
+; BIOS GDT, stack and and CS selector are restored.
+;
+;
+;-----------------------------------------------------------------------------
+
+ ;
+ ; Reload the GDTR. Upon return CPU is loaded with selector from ACM GDT
+ ; The following instruction works simply because whatever CS selector is
+ ; currently, it is flat selector.
+ ;
+% _movd eax, SAVED_GDT
+ lgdt FWORD ptr [rax] ; lgdt FWORD ptr [eax] - in 32 bit mode
+
+ ;
+ ; Restore the stack
+ ;
+% _movd eax, SAVED_EBP
+ mov ebp, eax ; restore ebp
+% _movd eax, SAVED_ESP
+ mov esp, eax ; restore esp
+% _movd eax, SAVED_SS
+ mov ss, ax ; restore ss
+
+ ;
+ ; Reload cs register
+ ;
+ mov eax, DWORD PTR CompModeSel
+ push rax ; push eax - in 32 bit mode
+
+ mov eax, DWORD PTR CompModeOff
+ push rax ; push eax - in 32 bit mode
+ retf ; will jump to Protected label below
+
+ProtectedMode2:
+
+;-----------------------------------------------------------------------------
+;
+; Section: Restore MTRRs
+;
+; Description: BIOS MTRR values are restored.
+;
+;-----------------------------------------------------------------------------
+ ;
+ ; Disable paging
+ ;
+ mov rax, cr0
+ and eax, DWORD PTR (NOT CR0_PG_MASK)
+ mov cr0, rax
+
+ mov rcx, MTRR_COUNT
+ lea ebx, MtrrTab
+
+RestoreNextMtrr:
+ add ecx, IA32_MTRR_PHYSBASE0 - 1
+ mov eax, DWORD PTR [rbx+0] ; mov eax, DWORD PTR [ebx+0] - in 32 bit mode
+ mov edx, DWORD PTR [rbx+8] ; mov eax, DWORD PTR [ebx+8] - in 32 bit mode
+ wrmsr
+ sub ecx, IA32_MTRR_PHYSBASE0 - 1
+ add ebx, 10h
+ loop RestoreNextMtrr
+
+ mov rcx, IA32_MTRR_DEF_TYPE
+ mov rdx, MtrrTypeRdx
+ mov rax, MtrrTypeRax
+ wrmsr
+;-----------------------------------------------------------------------------
+;
+; Section: Switch to compatibility mode
+;
+; Description: Compatibility mode i srestored by enabling of paging -
+; this is done by restoring CR4 contenxt, and setting of LME bit.
+;
+;-----------------------------------------------------------------------------
+
+ ;
+ ; Enable PAE in CR4
+ ;
+ mov eax, DWORD PTR SavedCR4
+ or eax, CR4_PAE
+ mov cr4, rax
+
+ ;
+ ; Reload CR3
+ ;
+ mov eax, DWORD PTR SavedCR3
+ mov cr3, rax
+
+ ;
+ ; Set EFER.LME to re-enable ia32-e
+ ;
+ mov ecx, IA32_EFER_MSR
+ rdmsr
+ or eax, LME
+ wrmsr
+ ;
+ ; Enable paging
+ ;
+ mov rax, cr0
+ or eax, CR0_PG_MASK
+ mov cr0, rax
+
+ jmp CompatibilityMode2
+
+CompatibilityMode2:
+ wbinvd ; Flush and invalidate the cache
+ ;
+ ; Now we're in Compatibility mode - restore segment registers.
+ ;
+ mov rax, SavedDS
+ mov ds, ax
+ mov rax, SavedES
+ mov es, ax
+ mov rax, SavedGS
+ mov gs, ax
+ mov rax, SavedFS
+ mov fs, ax
+ ;
+ ; Reastore IA32_MISC_ENABLES MSR
+ ;
+ mov rcx, IA32_MISC_ENABLE_MSR
+ mov rdx, SavedMiscEnablesRdx
+ mov rax, SavedMiscEnablesRax
+ wrmsr
+
+
+;-----------------------------------------------------------------------------
+;
+; Section: Switch to long mode
+;
+; Description: Previously saved selector and offset are used to return
+; CPU to long mode.
+;
+;-----------------------------------------------------------------------------
+ ;
+ ; Reload cs register
+ ;
+ mov eax, DWORD PTR LongModeSel
+ push rax ; push eax - in 32 bit mode
+
+ mov eax, DWORD PTR LongModeOff
+ push rax ; push eax - in 32 bit mode
+ retf
+
+LongMode2:
+;-----------------------------------------------------------------------------
+;
+; Section: Resore registers, stack and exit.
+;
+; Description: Previously saved registers are restored. Stack is restored
+; by execution leave instruction and control is returned to
+; caller.
+;
+; NOTE!
+; This section ends differences between programmed and
+; executed code.
+;
+;-----------------------------------------------------------------------------
+ ;
+ ; Now we're in Long Mode
+ ; Restore control registers
+ ;
+ mov rax, SavedCR4
+ mov cr4, rax
+
+ POPA_64
+ popf
+
+ leave
+ ret 0
+
+LaunchBiosAcm ENDP
+
+_TEXT ENDS
+
+ END
diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/TxtPeiAp.asm16 b/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/TxtPeiAp.asm16
new file mode 100644
index 0000000..9855257
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/TxtPeiAp.asm16
@@ -0,0 +1,305 @@
+;/*++
+; 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
+;--*/
+;
+;/*++
+;
+; Copyright (c) 1999 - 2011 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:
+;
+; TxtPeiAp.asm
+;
+; Abstract:
+;
+; This file contains AP initialization code in PEI phase
+;
+;--*/
+
+ .XLIST
+ include txt.inc
+ .LIST
+
+ .586p
+ .MMX
+
+TxtSegment16 SEGMENT PARA USE16 PUBLIC 'TXTCODE'
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure:
+;
+; Input: None
+;
+; Output: None
+;
+; Registers: None are preserved
+;
+; Description: Entry point of AP startup code. Target of SIPI vector.
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+;
+; This point is 4K aligned somewhere in boot block.
+;
+ jmp code16bitStart
+
+ ORG 10h
+
+GDTAddress:
+ dw GDTLen ; The length of the GDT
+ dd OFFSET GDTStart ; The 32-bit physical address
+
+;
+; AP GDT table
+;
+ ALIGN 16
+GDTStart LABEL BYTE
+
+ SEG_DESCRIPTOR <> ; Unused (selector 0)
+
+;
+; Selector 8
+;
+TXT_DATA32 EQU $ - GDTStart
+
+TXT_DATA32_OFF SEG_DESCRIPTOR {0FFFFh,\
+ 0000h, \
+ 00h, \
+ <SEG_PRESENT, 0, APPLSEGMENT, DATATYPE>, \
+ <PAGEGRANULARITY, BIGSEGMENT,,,0Fh>, \
+ 00h}
+
+GDTLen EQU $ - GDTStart - 1
+
+
+code16bitStart:
+
+;L1: jmp $
+ cli
+
+ mov si, OFFSET GDTAddress
+ ;
+ ; Set DS and ES limits
+ ;
+ db 66h ; Force 32 bit load
+ lgdt FWORD PTR cs:[si]
+
+ mov eax, CR0 ; get CPU control word 0
+ or al, 01 ; enable CPU protected mode
+ mov CR0, eax ; write back to CPU control word 0
+ jmp target
+
+target:
+
+ mov ax, TXT_DATA32
+ mov ds, ax ; set DS limit
+ mov es, ax ; set ES limit
+ mov fs, ax ; set FS limit
+ mov gs, ax ; set GS limit
+ mov ss, ax ; set SS limit
+
+ ;
+ ; Disable protected mode
+ ;
+ mov eax, CR0 ; get CPU control word 0
+ and al, 0FEh ; disable CPU protected mode
+ mov CR0, eax ; write back to CPU control word 0
+ jmp target3
+
+target3:
+ xor ax, ax
+ mov ds, ax ; set flat DS
+ mov es, ax ; set flat ES
+
+ ;
+ ; Fall through to main code
+ ;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+;
+; Procedure: LoadVsmcuRetNS - Variable Size Processor Microcode Update (Stackless)
+;
+; Input: SP = Return address
+;
+; Output: None
+;
+; Registers: All but SP are modified
+;
+; Description:
+; Load MCU into processor.
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+
+LoadVsmcuRetNS PROC NEAR PUBLIC
+ ;
+ ; Check uCode was loaded or not
+ ;
+ xor eax, eax
+ xor edx, edx
+ mov ecx, MCU_REV_MSR
+ wrmsr
+ mov eax, 1
+ cpuid
+ mov ecx, MCU_REV_MSR
+ rdmsr
+ or edx, edx
+ jnz uCode_loaded
+
+ ;
+ ; Restore MCU address from scratch register
+ ;
+ mov eax, 1
+ cpuid
+
+ mov eax, TXT_PUBLIC_BASE + MCU_BASE_ADDR
+ mov eax, [eax]
+
+ lea eax, [eax + SIZEOF MCU] ; EAX -> MCU data (after header)
+ xor edx, edx
+ mov ecx, MCU_LOAD_MSR ; Trigger to load MCU
+
+ wrmsr ; Load MCU
+
+ mov eax, 1
+ cpuid
+uCode_loaded:
+ ;
+ ; Fall through
+ ;
+LoadVsmcuRetNS ENDP
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: TxtPrepareCacheForAcModuleRetNS
+;
+; Input: None
+;
+; Output: None
+;
+; Registers: None are preserved
+;
+; Description: Cache initialization per TXT BIOS spec
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+
+TxtPrepareCacheForAcModuleRetNS PROC NEAR PUBLIC
+
+ ;
+ ; Ensure CR0.CD and CR0.NW are cleared
+ ;
+ mov eax, cr0 ;
+ and eax, NOT (CR0_CD_MASK + CR0_NW_MASK)
+ mov cr0, eax
+ ;
+ ; Fall through
+ ;
+TxtPrepareCacheForAcModuleRetNS ENDP
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: TxtCleanMcaNS
+;
+; Input: None
+;
+; Output: None
+;
+; Registers: None are preserved
+;
+; Description: MCA registers are cleaned
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+
+TxtCleanMcaNS PROC NEAR PUBLIC
+ ;
+ ; Clean MC[i]_STATUS MSR registers
+ ; SCLEAN will generate GPF otherwise
+ ;
+ mov ecx, MCG_CAP
+ rdmsr
+ movzx ebx, al ; Bank count to ebx
+ sub eax, eax ; Write 0 into all MCi_STATUS registers
+ sub edx, edx
+ mov ecx, MC0_STATUS
+
+McaErrorCleanLoopStart:
+ wrmsr
+ dec ebx
+ jz continue
+ add ecx, 4 ; Number of MSRs per bank
+ jmp McaErrorCleanLoopStart
+
+continue:
+ ;
+ ; Fall through
+ ;
+TxtCleanMcaNS ENDP
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: TxtHaltLoopNS
+;
+; Input: None
+;
+; Output: None
+;
+; Registers: None are preserved
+;
+; Description: APs enter halt loop
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+TxtHaltLoopNS PROC NEAR PUBLIC
+
+ mov eax, CR4
+ or eax, CR4_OSFXSR + CR4_DE + CR4_SMXE
+ mov CR4, eax
+
+ mov eax, 1
+ cpuid
+ shr ebx, 24 ; ebx is initial APIC ID shifted rightmostly
+
+ ;
+ ; Since accesses to semaphore cannot be serialized, accesses among different CPUs
+ ; are orchestrated as following:
+ ; BSP will only READ semaphore
+ ; All APs will keep READING semaphore until its value EQUALS to that AP's
+ ; APIC ID minus 1. Only AFTER that AP will INCREMENT semaphore.
+ ; This allows BSP to judge WHEN all APs finished.
+ ;
+ mov ecx, [TXT_PUBLIC_BASE + SEMAPHORE]
+
+keepWaiting:
+ mov eax, [ecx]
+ inc eax
+ cmp eax, ebx
+ jb keepWaiting
+ ja hltLoop
+ mov [ecx], eax
+
+hltLoop:
+ cli
+ hlt
+ jmp hltLoop
+
+TxtHaltLoopNS ENDP
+
+TxtSegment16 ENDS
+
+END
diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/TxtPeiAp.inf b/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/TxtPeiAp.inf
new file mode 100644
index 0000000..a6e8185
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/TxtPeiAp.inf
@@ -0,0 +1,35 @@
+## @file
+# Component description file for TXTPEIAP module
+#
+#@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
+#
+
+[defines]
+BASE_NAME = TxtPeiAp
+FILE_GUID = D1E59F50-E8C3-4545-BF61-11F002233C97
+COMPONENT_TYPE = USER_DEFINED
+
+[sources.common]
+
+[sources.ia32]
+ TxtPeiAp.asm16
+
+[includes.common]
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include
+
+[libraries.common]
+
+[nmake.common]
diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/TxtPeiApV7.inf b/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/TxtPeiApV7.inf
new file mode 100644
index 0000000..e649127
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/TxtPeiApV7.inf
@@ -0,0 +1,35 @@
+## @file
+# Component description file for TXTPEIAP module
+#
+#@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
+#
+
+[defines]
+BASE_NAME = TxtPeiAp
+FILE_GUID = D1E59F50-E8C3-4545-BF61-11F002233C97
+COMPONENT_TYPE = FILE
+BUILD_TYPE = MAKEFILE
+
+[sources.common]
+
+[sources.ia32]
+ TxtPeiAp.asm16
+
+[includes.common]
+
+[libraries.common]
+
+[nmake.common]
diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/TxtPeiBsp.asm b/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/TxtPeiBsp.asm
new file mode 100644
index 0000000..066aedc
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/TxtPeiBsp.asm
@@ -0,0 +1,1387 @@
+;/*++
+; 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
+;--*/
+;
+;/*++
+;
+; Copyright (c) 1999 - 2011 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:
+;
+; TxtPeiBsp.asm
+;
+; Abstract:
+;
+; This file contains the code to launch BIOS ACM functions in PEI phase
+;
+;--*/
+
+ .XLIST
+ include txt.inc
+ .LIST
+
+ .686P
+ .MMX
+ .XMM
+ .MODEL FLAT,C
+ .CODE
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: LaunchBiosAcmSclean
+;
+; Input: None
+;
+; Output: None
+;
+; Registers: None are preserved
+;
+; Description: Setup GETSEC environment (protected mode, mtrrs, etc) and
+; invoke GETSEC:ENTERACCS with requested BIOS ACM entry point.
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+
+LaunchBiosAcmSclean PROC PUBLIC
+ ;
+ ; Tell where we are
+ ;
+ mov eax, 11110000h
+ in ax, 80h
+ mov ah, PORT80_CODE_PREFIX + TXT_LAUNCH_SCLEAN
+ out 80h, eax
+
+ ;
+ ; Enable SMXE, SSE and debug extensions always.
+ ;
+ mov eax, CR4
+ or eax, CR4_OSFXSR + CR4_DE + CR4_SMXE
+ mov CR4, eax
+
+ ;
+ ; Prepare cache of BSP
+ ;
+ mov esi, TXT_PUBLIC_BASE + BIOACM_ADDR
+ mov edi, 0
+
+ CALL_NS PrepareCacheForAcModuleRetNS
+
+ CALL_NS CleanMcaRetNS
+
+ifdef MKF_TXT_RLP_INIT
+ if MKF_TXT_RLP_INIT
+ CALL_NS InitializeApsRetNS
+ endif
+endif
+
+
+ ;
+ ; Call GETSEC[ENTERACCS]
+ ;
+ cli
+ mov eax, ENTERACCS ; eax = ENTERACCS
+ mov ebx, TXT_PUBLIC_BASE + BIOACM_ADDR
+ mov ebx, [ebx]
+ mov ecx, [ebx].ACM_HEADER.AcmSize
+ shl ecx, 2
+ xor edx, edx
+ xor edi, edi
+ mov esi, 0
+
+ _GETSEC
+
+ jmp DoPowerCycleReset
+LaunchBiosAcmSclean ENDP
+
+DoGlobalReset PROC PUBLIC
+ mov dx, 0CF8h ; Make warm system reset through port 0CF9h
+ mov eax, 8000F8ACh ; to be global system reset - set bit 20
+ out dx, eax ; of device 1F
+ mov dx, 0CFCh
+ in eax, dx
+ or eax, (1 SHL 20)
+ out dx, eax
+
+ mov dx, 0CF9h ; After return from SCLEAN function
+ mov al, 0 ; system must be reset.
+ out dx, al
+ mov dx, 0CF9h ; After return from SCLEAN function
+ mov al, 6 ; system must be reset.
+ out dx, al
+ cli
+ hlt
+ jmp $
+
+DoGlobalReset ENDP
+
+DoPowerCycleReset PROC PUBLIC
+ mov dx, 0CF8h ; Make warm system reset through port 0CF9h
+ mov eax, 8000F8ACh ; to be global system reset - set bit 20
+ out dx, eax ; of device 1F
+ mov dx, 0CFCh
+ in eax, dx
+ and eax, NOT (1 SHL 20)
+ out dx, eax
+
+ mov dx, 0CF9h ; After return from SCLEAN function
+ mov al, 0 ; system must be reset.
+ out dx, al
+ mov dx, 0CF9h ; After return from SCLEAN function
+ mov al, 0Eh ; system must be reset.
+ out dx, al
+ cli
+ hlt
+ jmp $
+
+DoPowerCycleReset ENDP
+
+DoHostReset PROC PUBLIC
+ mov dx, 0CF8h ; Make warm system reset through port 0CF9h
+ mov eax, 8000F8ACh ; to be global system reset - set bit 20
+ out dx, eax ; of device 1F
+ mov dx, 0CFCh
+ in eax, dx
+ and eax, NOT (1 SHL 20)
+ out dx, eax
+
+ mov dx, 0CF9h ; After return from SCLEAN function
+ mov al, 0 ; system must be reset.
+ out dx, al
+ mov dx, 0CF9h ; After return from SCLEAN function
+ mov al, 6 ; system must be reset.
+ out dx, al
+ cli
+ hlt
+ jmp $
+
+DoHostReset ENDP
+
+DoCpuReset PROC PUBLIC
+ mov dx, 0CF8h ; Make warm system reset through port 0CF9h
+ mov eax, 8000F8ACh ; to be global system reset - clear bit 20
+ out dx, eax ; of device 1F
+ mov dx, 0CFCh
+ in eax, dx
+ and eax, NOT (1 SHL 20)
+ out dx, eax
+
+ mov dx, 0CF9h ; Issue a CPU only reset by CF9h
+ mov al, 0 ; toggle bit2 from 0 to 1
+ out dx, al
+ mov dx, 0CF9h ; Issue a CPU only reset by CF9h
+ mov al, 4 ;
+ out dx, al
+ cli
+ hlt
+ jmp $
+
+DoCpuReset ENDP
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: PrepareCacheForAcModuleRetNS
+;
+; Input: esi - bios acm address
+; edi - in memory flag
+;
+; Output: None
+;
+; Registers: None are preserved
+;
+; Description: MTRRs are set per BIOS spec
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+
+PrepareCacheForAcModuleRetNS PROC FAR PUBLIC
+ ;
+ ; Enable local APIC
+ ;
+ mov ecx, IA32_APIC_BASE
+ rdmsr ; Get APIC Base
+ and eax, BASE_ADDR_MASK ; Just need the address
+ mov DWORD PTR [eax+SPURIOUS_VECTOR_1], 1FFh ; Enable APIC, keep spurious vector
+ ;
+ ; Disable cache
+ ;
+ mov eax, cr0 ; set CR0:CD and CR0:NE, clear CR0:NW
+ or eax, CR0_CD_MASK OR CR0_NE_MASK
+ and eax, NOT CR0_NW_MASK
+ mov cr0, eax
+ cmp edi, 0
+ je @F ; JIf stackless environment
+ wbinvd ; Invalidate the cache
+ jmp disableMtrrs
+
+@@:
+ invd
+
+disableMtrrs:
+ ;
+ ; Disable all MTRRs
+ ;
+ xor eax, eax
+ xor edx, edx
+ mov ecx, IA32_MTRR_DEF_TYPE
+ wrmsr
+
+ ;
+ ; Disable NEM
+ ;
+ mov ecx, NO_EVICT_MODE
+ rdmsr
+ and eax, NOT (BIT1)
+ wrmsr ; Clear No-Eviction Mode Run bit
+ mov ecx, NO_EVICT_MODE
+ rdmsr
+ and eax, NOT (BIT0)
+ wrmsr ; Clear No-Eviction Mode SETUP bit
+
+ invd
+
+ ;
+ ; Clear all variable MTRRs
+ ;
+ mov ecx, IA32_MTRR_CAP
+ rdmsr
+ and eax, 0FFh
+ shl eax, 1
+ mov ecx, eax
+ xor eax, eax
+ xor edx, edx
+@@:
+ add ecx, IA32_MTRR_PHYSBASE0 - 1
+ wrmsr
+ sub ecx, IA32_MTRR_PHYSBASE0 - 1
+ loop @B
+
+ ;
+ ; Determine size of AC module
+ ;
+ mov esi, [esi]
+ mov eax, [esi].ACM_HEADER.AcmSize
+ shl eax, 2 ; ...in bytes (ACM header has size in dwords)
+ ;
+ ; Round up to page size
+ ;
+ mov ecx, eax ; Save
+ and ecx, 0FFFFF000h ; Number of pages in AC module
+ and eax, 0FFFh ; Number of "less-than-page" bytes
+ jz rounded
+ mov eax, 1000h ; Add the whole page size
+
+rounded:
+ add eax, ecx ; eax - rounded up AC module size
+
+ ;
+ ; Define "local" vars for this routine
+ ;
+ ACM_SIZE_TO_CACHE TEXTEQU <mm0>
+ ACM_BASE_TO_CACHE TEXTEQU <mm1>
+ NEXT_MTRR_INDEX TEXTEQU <mm2>
+ NEXT_MTRR_SIZE TEXTEQU <mm3>
+ ;
+ ; Initialize "locals"
+ ;
+ sub ecx, ecx
+ movd NEXT_MTRR_INDEX, ecx ; Start from MTRR0
+
+ ;
+ ; Save remaining size to cache
+ ;
+ movd ACM_SIZE_TO_CACHE, eax ; Size of ACM that must be cached
+ movd ACM_BASE_TO_CACHE, esi ; Base ACM address
+
+nextMtrr:
+ ;
+ ; Get remaining size to cache
+ ;
+ movd eax, ACM_SIZE_TO_CACHE
+ and eax, eax
+ jz done ; 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 esi, ACM_BASE_TO_CACHE
+ bsf ecx, esi ; 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_VALID ; Set valid bit
+
+ ;
+ ; Program mask register
+ ;
+ mov ecx, IA32_MTRR_PHYSMASK0 ; setup variable mtrr
+ movd ebx, NEXT_MTRR_INDEX
+ add ecx, ebx
+
+ mov edx, 0Fh ; 8K range (FFFFFFE800)
+ wrmsr
+ ;
+ ; Program base register
+ ;
+ sub edx, edx
+ mov ecx, IA32_MTRR_PHYSBASE0 ; setup variable mtrr
+ add ecx, ebx ; ebx is still NEXT_MTRR_INDEX
+
+ movd eax, ACM_BASE_TO_CACHE
+ or eax, WB ; set type to write back
+ wrmsr
+ ;
+ ; Advance and loop
+ ; Reduce remaining size to cache
+ ;
+ movd ebx, ACM_SIZE_TO_CACHE
+ movd eax, NEXT_MTRR_SIZE
+ sub ebx, eax
+ movd ACM_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, ACM_BASE_TO_CACHE
+ movd eax, NEXT_MTRR_SIZE
+ add ebx, eax
+ movd ACM_BASE_TO_CACHE, ebx
+
+ jmp nextMtrr
+
+done:
+ ;
+ ; Enable variable MTRRs
+ ;
+ xor edx, edx
+ mov eax, MTRR_ENABLE; enable mtrrs (but not fixed ones)
+ mov ecx, IA32_MTRR_DEF_TYPE
+ wrmsr
+ ;
+ ; Enable cache
+ ;
+ mov eax, cr0 ; Enable caching - WB (NW stays clear)
+ and eax, NOT CR0_CD_MASK
+ mov cr0, eax
+
+ RET_NS
+PrepareCacheForAcModuleRetNS ENDP
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: CleanMcaRetNS
+;
+; Input: None
+;
+; Output: None
+;
+; Registers: None are preserved
+;
+; Description: Setup GETSEC environment (protected mode, mtrrs, etc)
+; invoke GETSEC:ENTERACCS with requested module
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+
+CleanMcaRetNS PROC NEAR PUBLIC
+
+ ;
+ ; Clean all MCi_STATUS MSR registers
+ ; SCLEAN will generate GPF otherwise
+ ;
+ mov ecx, MCG_CAP
+ rdmsr
+ movzx ebx, al ; Bank count to ebx
+ sub eax, eax ; Write 0 into all MCi_STATUS registers
+ sub edx, edx
+ mov ecx, MC0_STATUS
+
+McaErrorCleanLoopStart:
+ wrmsr
+ dec ebx
+ jz exit
+ add ecx, 4 ; Number of MSRs per bank
+ jmp McaErrorCleanLoopStart
+
+exit:
+ RET_NS
+CleanMcaRetNS ENDP
+
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: InitializeApsRetNS
+;
+; Input: None
+;
+; Output: None
+;
+; Registers: None are preserved
+;
+; Description:
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+InitializeApsRetNS PROC NEAR
+ mov eax, 1
+ cpuid
+ shr ebx, 16 ; Total Logical Proc Count in BL
+ cmp bl, 1 ; If 1 thread - nothing to do
+ je exit
+
+ ;
+ ; Init Timer 1
+ ;
+ mov al, 54h
+ out 43h, al
+ mov al, 12h
+ out 41h, al
+
+ ;
+ ; More than one thread
+ ; Get APIC address
+ ;
+ mov ecx, IA32_APIC_BASE
+ rdmsr ; Get APIC Base
+ and eax, BASE_ADDR_MASK ; Just need the address
+ mov edi, eax ; edi points to APIC base
+
+ mov esi, TXT_PUBLIC_BASE ; esi points to public space
+
+ ;
+ ; Wait for APIC ready
+ ;
+ mov edx, IcrStatusRetNs
+ mov ecx, 15
+ CALL_NS ltWaitStatusRetNS
+
+ ;
+ ; Broadcast INIT message to put all APs into Wait for SIPI state
+ ; C0500 -> Destination = All excl self, Delivery = INIT
+ ;
+ mov DWORD PTR ICR_LOW[edi], 000C0500h
+ mov edx, NeverStatusRetNS
+ mov ecx, 667
+ CALL_NS ltWaitStatusRetNS ; Wait full 10ms
+ ;
+ ; Create vector used in the following SIPI message
+ ; Below address is the real mode address of AP code in Boot Block
+ ; LTCACHE.BIN containg AP thread code must be placed at the above address
+ ; in Boot block (FFFF0000h). See file LTCACHE.ASM
+ ;
+
+ mov ebx, [esi+APINIT_ADDR]
+ shr ebx, 12
+ and ebx, 0FFh
+ or ebx, 0C0600h ; This is message
+
+ ;
+ ; Broadcast SIPI message with our vector
+ ; Wait for APIC ready
+ ;
+ mov edx, IcrStatusRetNs
+ mov ecx, 15
+ CALL_NS ltWaitStatusRetNS
+ ;
+ ; Send message
+ ;
+ mov ICR_LOW[edi], ebx
+ ;
+ ; Wait 200us as recommended
+ ;
+ mov edx, NeverStatusRetNS
+ mov ecx, 14
+ CALL_NS ltWaitStatusRetNS
+ ;
+ ; Broadcast second SIPI message with our vector
+ ; Wait for APIC ready
+ ;
+ mov edx, IcrStatusRetNs
+ mov ecx, 15
+ CALL_NS ltWaitStatusRetNS
+ ;
+ ; Send message
+ ;
+ mov ICR_LOW[edi], ebx
+ ;
+ ; Wait for semaphore reflect number of CPUs
+ ;
+ mov eax, 1
+ cpuid
+ shr ebx, 16 ; Total Logical Proc Count in BL
+ dec bl ; bl is number of APs
+
+ mov edx, SemaphoreStatusRetNS
+ mov ecx, 6670
+ CALL_NS ltWaitStatusRetNS ; Wait for up to 100ms
+
+ ;
+ ; Broadcast INIT message to put all APs back into Wait for SIPI state
+ ; Wait for APIC ready
+ ;
+ mov edx, IcrStatusRetNs
+ mov ecx, 15
+ CALL_NS ltWaitStatusRetNS
+ ;
+ ; Send message
+ ;
+ mov DWORD PTR ICR_LOW[edi], 000C0500h
+
+ mov edx, NeverStatusRetNS
+ mov ecx, 667
+ CALL_NS ltWaitStatusRetNS ; Wait full 10ms
+
+exit:
+ RET_NS
+InitializeApsRetNS ENDP
+
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: SaveApConfig
+;
+; Input: ApCfg - pointer to save area
+;
+; Output: None
+;
+; Registers: All are preserved
+;
+; Description: Function is called in memory present environment on S3 resume
+; path. Saves contents of all MTRRs into table plus some registers.
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+SaveApConfig PROC NEAR PUBLIC, ApCfg:PTR QWORD
+
+ pushad
+
+ mov esi, ApCfg
+ mov ecx, IA32_MTRR_CAP
+ rdmsr
+ and eax, 0FFh
+ shl eax, 1
+ mov ecx, eax
+
+@@:
+ add ecx, IA32_MTRR_PHYSBASE0 - 1
+ rdmsr
+ mov [esi], eax
+ mov [esi+4], edx
+ add esi, SIZEOF QWORD
+ sub ecx, IA32_MTRR_PHYSBASE0 - 1
+ loop @B
+
+ mov ecx, IA32_MTRR_DEF_TYPE
+ rdmsr
+ mov [esi], eax
+ mov [esi+4], edx
+
+ sidt [esi+8]
+
+ mov ecx, IA32_MISC_ENABLE_MSR
+ rdmsr
+ mov [esi+010h], eax
+ mov [esi+014h], edx
+
+ popad
+ ret
+SaveApConfig ENDP
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: StartupAllAPs
+;
+; Input: pFunction - pointer to function to execute on AP
+; pParam - pointre to pFunction parameters
+;
+; Output: None
+;
+; Registers: All are preserved
+;
+; Description: Procedure is called in memmory present enironment on S3
+; resume path and is executed on BSP
+; It saves memory at address 1000h into buffer
+; It then copies AP start-up code into address 1000h
+; Then variables in the 1000h area are updated and APs are started
+; After APs finish execution of function passed as parameter they
+; are halted. BSP restores contents 1000h area from buffer and
+; returns.
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+
+Func TYPEDEF PROTO
+
+PFUNC TYPEDEF PTR Func
+
+StartUp STRUCT
+ db 0FAh ; cli
+ db 066h, 0BBh ; mov ebx, OFFSET gdtLim
+ db StartUp.gdtLim, 0,0,0
+ db 066h
+ db 067h, 02Eh, 00Fh, 001h, 013h ; lgdt FWORD PTR cs:[ebx]
+ db 00Fh, 020h, 0C0h ; mov eax, CR0
+ db 00Ch, 001h ; or al, 01
+ db 00Fh, 022h, 0C0h ; mov CR0, eax
+ ;
+ ; 32 bit jump to 32 bit Function handler
+ ;
+ db 066h
+ db 0eah
+fOff dd 0
+fCs dw 0
+
+ ALIGN 16
+fDs dw 0
+gdtLim dw ? ; Size of LT GDT in bytes
+gdtBas dd ? ; Physical address of LT GDT
+fParam dd ?
+smphr dd ?
+StartUp ENDS
+
+
+StartupAllAPs PROC NEAR, pFunction:PFUNC, pParam:PTR QWORD
+ LOCAL buffer:StartUp
+ LOCAL savedESP:DWORD
+
+ pushad
+ mov savedESP, esp
+ mov eax, 1
+ cpuid
+ shr ebx, 16 ; Total Logical Proc Count in BL
+ cmp bl, 1 ; If 1 thread - nothing to do
+ je exit
+
+ ;
+ ; Init Timer 1
+ ;
+ mov al, 54h
+ out 43h, al
+ mov al, 12h
+ out 41h, al
+
+ ;
+ ; More than one thread. Prepare Startup area
+ ;
+ mov esi, 1000h ; Source
+ lea edi, buffer ; Destination
+ mov ecx, sizeof StartUp / 4
+ CALL_NS MemCopyRetNS
+
+ mov esi, offset ApHandler16 ; Source
+ mov edi, 1000h ; Destination
+ mov ecx, sizeof StartUp / 4
+ CALL_NS MemCopyRetNS
+ ;
+ ; Update Srartup area variables
+ ;
+ mov edi, 1000h
+ mov ds:[edi].StartUp.fCs, cs
+ mov ds:[edi].StartUp.fDs, ds
+ mov eax, pFunction
+ mov ds:[edi].StartUp.fOff, eax
+ sub eax, eax
+ mov ds:[edi].StartUp.smphr, eax
+ mov eax, pParam
+ mov ds:[edi].StartUp.fParam, eax
+ sgdt ds:[edi].StartUp.gdtLim
+
+ ;
+ ; Get APIC address
+ ;
+ mov ecx, IA32_APIC_BASE
+ rdmsr ; Get APIC Base
+ and eax, BASE_ADDR_MASK ; Just need the address
+ mov edi, eax ; edi points to APIC base
+
+ ;
+ ; Wait for APIC ready
+ ;
+ mov edx, IcrStatusRetNs
+ mov ecx, 15
+ CALL_NS ltWaitStatusRetNS
+
+ ;
+ ; Broadcast INIT message to put all APs into Wait for SIPI state
+ ; C0500 -> Destination = All excl self, Delivery = INIT
+ ;
+ mov DWORD PTR ICR_LOW[edi], 000C0500h
+ mov edx, NeverStatusRetNS
+ mov ecx, 667
+ CALL_NS ltWaitStatusRetNS ; Wait full 10ms
+ ;
+ ; Create vector used in the following SIPI message
+ ;
+ mov ebx, 0C0600h + (1000h SHR 12)
+ ;
+ ; Broadcast SIPI message with our vector
+ ; Wait for APIC ready
+ ;
+ mov edx, IcrStatusRetNs
+ mov ecx, 15
+ CALL_NS ltWaitStatusRetNS
+ ;
+ ; Send message
+ ;
+ mov ICR_LOW[edi], ebx
+ ;
+ ; Wait 200us as recommended
+ ;
+ mov edx, NeverStatusRetNS
+ mov ecx, 14
+ CALL_NS ltWaitStatusRetNS
+ ;
+ ; Broadcast second SIPI message with our vector
+ ; Wait for APIC ready
+ ;
+ mov edx, IcrStatusRetNs
+ mov ecx, 15
+ CALL_NS ltWaitStatusRetNS
+ ;
+ ; Send message
+ ;
+ mov ICR_LOW[edi], ebx
+ ;
+ ; Wait for semaphore reflect number of CPUs
+ ;
+ mov eax, 1
+ cpuid
+ shr ebx, 16 ; Total Logical Proc Count in BL
+ dec bl ; bl is number of APs
+
+ mov edx, SemaphoreStatus2RetNS
+ mov ecx, 6670
+ CALL_NS ltWaitStatusRetNS ; Wait for up to 100ms
+ ;
+ ; Restore StartUp area
+ ;
+ lea esi, buffer ; Source
+ mov edi, 1000h ; Destination
+ mov ecx, sizeof StartUp / 4
+ CALL_NS MemCopyRetNS
+
+exit:
+ mov esp, savedESP
+ popad
+ ret
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Section: ApHandler16
+;
+; Input: None
+;
+; Output: None
+;
+; Registers: Irrelevant
+;
+; Description: This code is copied over address 0:1000. After recieving SIPI
+; AP is directed to this address where it starts execution in real mode.
+; AP first switches to protected mode, loads the same GDT which is used
+; by BSP and jumps to Procedure at fCs:fOff
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+
+ ALIGN 16
+ ;
+ ; Note After coppying this code must be aligned on page boundary!
+ ;
+
+ApHandler16 StartUp <>
+
+StartupAllAPs ENDP
+
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: PutApsInWfs
+;
+; Input: None
+;
+; Output: None
+;
+; Registers: All are preserved
+;
+; Description: Procedure is called in memory present environment on S3 resume path.
+; INIT SIPI message is sent to all APs.
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+
+PutApsInWfs PROC PUBLIC
+ LOCAL savedESP:DWORD
+ pushad
+ mov savedESP, esp
+
+ mov eax, 1
+ cpuid
+ shr ebx, 16 ; Total Logical Proc Count in BL
+ cmp bl, 1 ; If 1 thread - nothing to do
+ je exit
+
+ ;
+ ; Get APIC address
+ ;
+ mov ecx, IA32_APIC_BASE
+ rdmsr ; Get APIC Base
+ and eax, BASE_ADDR_MASK ; Just need the address
+ mov edi, eax ; edi points to APIC base
+ ;
+ ; Broadcast INIT message to put all APs back into Wait for SIPI state
+ ; Wait for APIC ready
+ ;
+ mov edx, IcrStatusRetNs
+ mov ecx, 15
+ CALL_NS ltWaitStatusRetNS
+ ;
+ ; Send message
+ ;
+ mov DWORD PTR ICR_LOW[edi], 000C0500h
+
+ mov edx, NeverStatusRetNS
+ mov ecx, 667
+ CALL_NS ltWaitStatusRetNS ; Wait full 10ms
+
+exit:
+ mov esp, savedESP
+ popad
+ ret
+PutApsInWfs ENDP
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: LaunchBiosAcmScheck
+;
+; Input: None
+;
+; Output: None
+;
+; Registers: None are preserved
+;
+; Description: Setup GETSEC environment (protected mode, mtrrs, etc) and
+; invoke GETSEC:ENTERACCS with requested BIOS ACM entry point.
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+
+LaunchBiosAcmScheck PROC PUBLIC, BiosAcAddr:PTR QWORD
+
+ LOCAL SavedGdtr:QWORD
+ LOCAL SavedSS:dword
+ LOCAL SavedESP:dword
+ LOCAL SavedCS:dword
+ LOCAL SavedCR3:dword
+ pushf
+ cli
+ pushad
+ ;
+ ; Tell where we are
+ ;
+ in ax, 80h
+ mov ah, PORT80_CODE_PREFIX + TXT_LAUNCH_SCHECK
+ out 80h, ax
+ ;
+ ; Save control registers
+ ;
+ mov eax, cr4
+ push eax
+ mov eax, cr0
+ push eax
+ ;
+ ; Save segment registers
+ ;
+ push ds
+ push es
+ push gs
+ push fs
+ ;
+ ; Save CS
+ ;
+ sub eax, eax ; Clean upper word
+ mov ax, cs
+ mov SavedCS, eax
+ ;
+ ; Save stack at this level
+ ;
+ mov ax, ss
+ mov SavedSS, eax
+ mov SavedESP, esp
+ mov eax, cr3
+ mov SavedCR3, eax
+
+ ;
+ ; Save GDT
+ ;
+ sgdt SavedGdtr ; save value of gdtr in local variable
+ ;
+ ; Define "local" vars for this routine
+ ;
+ SAVED_EBP TEXTEQU <mm4>
+ ;
+ ; Save ebp in MMX register
+ ;
+ movd SAVED_EBP, ebp ; Size of ACM that must be cached
+
+ ;
+ ; Enable SMXE, SSE and debug extensions always.
+ ;
+ mov eax, CR4
+ or eax, CR4_OSFXSR + CR4_DE + CR4_SMXE
+ mov CR4, eax
+ ;
+ ; Prepare cache of BSP
+ ;
+ mov esi, BiosAcAddr
+ mov edi, 1
+
+ CALL_NS PrepareCacheForAcModuleRetNS
+
+ CALL_NS CleanMcaRetNS
+
+ ;
+ ; Call GETSEC[ENTERACCS]
+ ;
+ mov eax, ENTERACCS ; eax = ENTERACCS
+ mov ebx, BiosAcAddr
+ mov ebx, [ebx]
+ mov ecx, [ebx].ACM_HEADER.AcmSize
+ shl ecx, 2
+ xor edx, edx
+ mov edi, S3_RESUME_PATH
+ mov esi, 4
+
+ _GETSEC
+
+ ;
+ ; Return point after ACEXIT.
+ ;
+ movd ebp, SAVED_EBP
+ lea eax, SavedGdtr
+ lgdt FWORD PTR [eax]
+ mov eax, SavedSS
+ mov ss, ax
+ mov esp, SavedESP
+ mov eax, SavedCR3
+ mov cr3, eax
+ ;
+ ; Restore segment registers
+ ;
+ pop fs
+ pop gs
+ pop es
+ pop ds
+ ;
+ ; Restore control registers
+ ;
+ pop eax
+ ;
+ ;remain cache disabled until MTRRs restored
+ ;
+ or eax, CR0_CD_MASK
+ and eax, NOT CR0_NW_MASK
+ wbinvd
+;
+ mov cr0, eax
+ pop eax
+ mov cr4, eax
+ ;
+ ; Restore CS
+ ;
+ mov eax, SavedCS
+ push eax
+ push OFFSET ReloadCS
+ retf
+
+ReloadCS:
+ popad
+ popf
+ emms
+
+ ret
+LaunchBiosAcmScheck ENDP
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: RestoreMtrrProgramming
+;
+; Input: ApMtrrTab - pointer to save area
+;
+; Output: None
+;
+; Registers: All are preserved
+;
+; Description: Function is executed on BSP in memory present environment on S3
+; resume path. Restores contents of all MTRRs from table
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+RestoreMtrrProgramming PROC NEAR PUBLIC, ApMtrrTab:PTR QWORD
+ LOCAL savedESP:DWORD
+ pushad
+ mov savedESP, esp
+
+ mov esi, ApMtrrTab
+ CALL_NS RestoreMtrrProgrammingRetNS
+
+ mov esp, savedESP
+ popad
+ ret
+RestoreMtrrProgramming ENDP
+
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: RestoreMtrrProgrammingRetNS
+;
+; Input: esi - pointer to save area
+;
+; Output: None
+;
+; Registers: None are preserved
+;
+; Description: Restores contents of all MTRRs from table
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+RestoreMtrrProgrammingRetNS PROC NEAR PUBLIC
+ mov eax, cr0 ; set CR0:CD and CR0:NE, clear CR0:NW
+ or eax, CR0_CD_MASK OR CR0_NE_MASK
+ and eax, NOT CR0_NW_MASK
+ mov cr0, eax
+ wbinvd ; flush and invalidate the cache
+
+ xor edx, edx
+ mov eax, MTRR_ENABLE + MTRR_FIXED_ENABLE ; enable mtrrs
+ mov ecx, 2FFh
+ wrmsr
+
+ mov ecx, IA32_MTRR_CAP
+ rdmsr
+ and eax, 0FFh
+ shl eax, 1
+ mov ecx, eax
+
+@@:
+ add ecx, IA32_MTRR_PHYSBASE0 - 1
+ mov eax, [esi]
+ mov edx, [esi+4]
+ wrmsr
+ add esi, SIZEOF QWORD
+ sub ecx, IA32_MTRR_PHYSBASE0 - 1
+ loop @B
+
+ mov ecx, IA32_MTRR_DEF_TYPE
+ mov eax, [esi]
+ mov edx, [esi+4]
+ wrmsr
+ mov ecx, IA32_MISC_ENABLE_MSR
+ mov eax, [esi+010h]
+ mov edx, [esi+014h]
+ wrmsr
+
+ mov eax, cr0 ; Enable caching - WB (NW stays clear)
+ and eax, NOT CR0_CD_MASK
+ mov cr0, eax
+
+ RET_NS
+RestoreMtrrProgrammingRetNS ENDP
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: RestoreApConfig
+;
+; Input: esi - pointer to save area
+;
+; Output: None
+;
+; Registers: None are preserved
+;
+; Description: Function is executed on AP in memory present environment on S3
+; resume path. Restores contents of all MTRRs from table
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+RestoreApConfig PROC NEAR PUBLIC
+ mov eax, CR4
+ or eax, CR4_OSFXSR + CR4_DE
+ mov CR4, eax
+
+ mov esi, 1000h
+ mov ds, cs:[esi].StartUp.fDs
+ mov es, cs:[esi].StartUp.fDs
+ mov fs, cs:[esi].StartUp.fDs
+ mov gs, cs:[esi].StartUp.fDs
+ mov ss, cs:[esi].StartUp.fDs
+
+ mov esi, [esi].StartUp.fParam
+
+ CALL_NS RestoreMtrrProgrammingRetNS
+
+ lidt FWORD PTR [esi+8]
+
+ jmp updateSemaphore
+
+RestoreApConfig ENDP
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: DoApInit
+;
+; Input: Contents of startup area at 1000h
+;
+; Output: None
+;
+; Registers: None are preserved
+;
+; Description: Executed on AP. Persforms CPU initialization for running
+; of GETSEC
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+DoApInit PROC NEAR PUBLIC
+ mov eax, CR4
+ or eax, CR4_OSFXSR + CR4_DE + CR4_SMXE
+ mov CR4, eax
+
+ mov esi, 1000h
+ mov ds, cs:[esi].StartUp.fDs
+
+ mov esi, [esi].StartUp.fParam
+ mov edi, 1
+
+ CALL_NS PrepareCacheForAcModuleRetNS
+
+ CALL_NS CleanMcaRetNS
+
+updateSemaphore::
+ mov ecx, 1000h + StartUp.smphr
+ lock inc DWORD PTR [ecx]
+
+hltLoop:
+ cli
+ hlt
+ jmp hltLoop
+
+DoApInit ENDP
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: MemCopyRetNS
+;
+; Input: esi - from linear address
+; edi - to linear address
+; ecx - swap size in dwords
+; ds - flat segment
+;
+; Output: None
+;
+; Registers: None
+;
+; Description: Swaps contents of two input buffers.
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+
+MemCopyRetNS PROC NEAR
+
+start:
+ mov eax, ds:[esi] ; source
+ mov ds:[edi], eax
+ add esi, 4
+ add edi, 4
+ loop start
+ RET_NS
+MemCopyRetNS ENDP
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: ltWaitStatusRetNS
+;
+; Input: cx - Refresh bit Toggle count
+; 750000us = 50000 toggles
+; edx - offset of Status procedure
+;
+; Output: Z if status is met
+; NZ - timeout occured
+; NC - always
+;
+; Stack: Not available
+;
+; Registers: cx, ax, esp
+;
+; Description: Calls status procedure. If status is met - returns Z and
+; NZ otherwise.
+; Status procedure is required to return Z if status is met and
+; NZ if not
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+ltWaitStatusRetNS PROC NEAR
+
+ in al, PORTB ; Read initial setting.
+ and al, PORTBMASK ; Keep what we care about.
+ mov ah, al ; Keep a copy of the data.
+
+waitLoop:
+ CALL_NS edx ; Call status procedure.
+ jz exit ; Z - status met
+
+waitLoop0:
+ in al, PORTB
+ and al, PORTBMASK
+ cmp al, ah ; Refresh bit changed ?
+ je waitLoop0
+
+ mov ah, al
+ loop waitLoop
+ or ax, 1 ; Clear the ZERO flag - timeout.
+ ; This also clears C flag
+exit:
+ RET_NS
+ltWaitStatusRetNS ENDP
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: IcrStatusRetNS
+;
+; Input: ds: Flat, edi - xAPIC Base Address
+;
+; Output: Z if status is met
+;
+; Stack: Not available
+;
+; Registers: all are preserved
+;
+; Description: Returns Z if ICR is idle
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+IcrStatusRetNS PROC NEAR PUBLIC
+ test DWORD PTR ICR_LOW[edi], BIT12
+ RET_NS
+IcrStatusRetNS ENDP
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: SemaphoreStatusRetNS
+;
+; Input: ds: Flat
+;
+; Output: Z if status is met
+;
+; Stack: Not available
+;
+; Registers: all are preserved
+;
+; Description: Returns Z if semaphore is 0
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+SemaphoreStatusRetNS PROC NEAR PUBLIC
+ bswap eax
+ mov al, BYTE PTR [esi+SEMAPHORE]
+ cmp al, bl
+ bswap eax
+ RET_NS
+SemaphoreStatusRetNS ENDP
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: SemaphoreStatus2RetNS
+;
+; Input: ds: Flat
+;
+; Output: Z if status is met
+;
+; Stack: Not available
+;
+; Registers: Upper byte of eax is modified
+;
+; Description: Returns Z if semaphore is 0
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+SemaphoreStatus2RetNS PROC NEAR PUBLIC
+ bswap eax
+ mov al, BYTE PTR [esi].StartUp.smphr
+ cmp al, bl
+ bswap eax
+ RET_NS
+SemaphoreStatus2RetNS ENDP
+
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+; Procedure: NeverStatusRetNS
+;
+; Input:
+;
+; Output: Z if status is met
+;
+; Stack: Not available
+;
+; Registers: All are preserved
+;
+; Description: Returns Z if ICR is idle
+;
+;-----------------------------------------------------------------------------
+;-----------------------------------------------------------------------------
+NeverStatusRetNS PROC NEAR PUBLIC
+ or dx, dx ; dx is never 0 so return is NZ
+ RET_NS
+NeverStatusRetNS ENDP
+
+
+
+END
diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/makefile.new b/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/makefile.new
new file mode 100644
index 0000000..e27781e
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/TxtInit/Pei/Ia32/makefile.new
@@ -0,0 +1,69 @@
+#++
+# 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 - 2011 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:
+#
+# makefile.new
+#
+# Abstract:
+#
+# makefile for TxtPeiAp.asm16 file
+#
+#--
+
+
+#
+# Globals
+#
+BIN_DIR = $(BUILD_DIR)\$(PROCESSOR)
+TOOLCHAIN = TOOLCHAIN_$(PROCESSOR)
+
+TOOLBIN_DIR = $(BUILD_DIR)\Tools
+
+#
+# Include CommonTools.env enviroment
+#
+
+!INCLUDE $(BUILD_DIR)\PlatformTools.env
+
+AP_GUID = D1E59F50-E8C3-4545-BF61-11F002233C97
+
+all : $(BIN_DIR)\TxtPeiAp.bin
+
+$(BIN_DIR)\TxtPeiAp.bin: $(BIN_DIR)\TxtPeiAp.obj
+
+$(BIN_DIR)\TxtPeiAp.obj: $(SOURCE_DIR)\TxtPeiAp.asm16
+ $(ASM) /c /nologo /Fl /Sa /I$(SOURCE_DIR)\..\..\..\..\Include /Fo$(BIN_DIR)\TxtPeiAp.obj $(SOURCE_DIR)\TxtPeiAp.asm16
+ cd $(BIN_DIR)
+ $(ASMLINK) TxtPeiAp.obj, TxtPeiAp.com,,,,
+ copy TxtPeiAp.com TxtPeiAp.bin
+ $(GENFFSFILE) -B $(BIN_DIR) -V -P1 <<$(BIN_DIR)\txtpeiap.pkg
+PACKAGE.INF
+[.]
+BASE_NAME = TxtPeiAp
+FFS_FILEGUID = $(AP_GUID)
+FFS_FILETYPE = EFI_FV_FILETYPE_RAW
+FFS_ATTRIB_CHECKSUM = FALSE
+FFS_ALIGNMENT = 5
+
+IMAGE_SCRIPT =
+{
+ txtpeiap.bin
+}
+<<KEEP
+
+
diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.c b/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.c
new file mode 100644
index 0000000..b1b1ec5
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.c
@@ -0,0 +1,241 @@
+/** @file
+ This is the main PEIM file for TXT. It represents an abstract outline of the
+ steps required during PEI for enabling TXT. Each individual step is further
+ abstracted behind a function call interface. This is intended to minimize
+ the need to modify this file when porting TXT to future platforms.
+
+@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 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
+
+**/
+
+///
+/// External include files do NOT need to be explicitly specified in real EDKII
+/// environment
+///
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGluePeim.h"
+#include "TxtPeiLib.h"
+///
+/// #include EFI_PPI_DEFINITION (BootScriptDone)
+///
+#include EFI_PPI_DEFINITION (TxtMemoryUnlocked)
+#include EFI_PPI_DEFINITION (EndOfPeiSignal)
+#include EFI_GUID_DEFINITION (TxtInfoHob)
+#include EFI_GUID_DEFINITION (SaDataHob)
+#endif
+
+STATIC EFI_PEI_PPI_DESCRIPTOR mPpiList = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gPeiTxtMemoryUnlockedPpiGuid,
+ NULL
+};
+
+STATIC EFI_PEI_NOTIFY_DESCRIPTOR mNotifyDesc = {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEndOfPeiSignalPpiGuid,
+ DprUpdate
+};
+
+/**
+ This is the entry point to the TXT PEIM. The TXT PEIM checks for an TXT
+ capable platform and determines whether SCLEAN should be run. If so,
+ it launches the BIOS ACM to run SCLEAN (which will reset the platform).
+ If not, the PEIM checks to see if the platform is resuming from S3.
+
+ If the platform is resuming from S3, this code will register a callback
+ so that SCHECK will be run when BootScript is done restoring the platform's
+ configuration.
+
+ @param[in] FfsHeader - A pointer the the FFS File containing this PEIM.
+ @param[in] PeiServices - A Pointer to the PEI Services Table.
+
+ @exception EFI_UNSUPPORTED - If the platform is not TXT capable.
+ @retval EFI_SUCCESS - In all other cases not listed above.
+**/
+EFI_STATUS
+EFIAPI
+PeimEntry (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ TXT_PEI_LIB_CONTEXT ctx;
+ BOOLEAN TxtEnvInitFail;
+ TxtEnvInitFail = FALSE;
+
+ ///
+ /// Install PPI to tell memory code that it can run.
+ /// Do it always.
+ ///
+ Status = PeiServicesInstallPpi (&mPpiList);
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Initialize the TXT PEI Lib functions
+ ///
+ Status = InitializeTxtPeiLib (
+ &ctx,
+ PeiServices
+ );
+
+ if (EFI_ERROR (Status)) {
+ TxtEnvInitFail = TRUE;
+ DEBUG ((EFI_D_ERROR, "TXTPEI::PEI Lib initialization failure\n"));
+ }
+ ///
+ /// Determine TPM presence. If TPM is not present - disabling TXT through TxtInfoHob by setting TxtMode=0
+ /// Incase TXT had been enabled but TPM was removed suddenly. Although TPM presence is precondition of this module
+ /// since all commands executed by BIOS ACM don't depend on TPM state.
+ /// TPM_NV_read will be successfully executed even if TPM is disabled
+ /// and/or deactivated because all indices defined for BIOS ACM
+ /// usage don't require authorization. TPM_ResetEstablishmentBit
+ /// doesn't depend on TPM state at all and can
+ /// be executed with disabled/deactivated TPM always.
+ /// Case when TPM is completely not functional is not considered.
+ ///
+ Status = IsTpmPresent (&ctx);
+ if (EFI_ERROR (Status)) {
+ ///
+ /// If TPM is not present / not supported, set TxtMode=0 incase TPM was removed after TXT enabled
+ ///
+ if (Status == EFI_UNSUPPORTED) {
+ DEBUG ((EFI_D_WARN, "TXTPEI::TPM Support is Disabled in BIOS! Disabling TXT! TxtMode=%x\n", ctx.Hob->Data.TxtMode));
+ } else {
+ DEBUG ((EFI_D_WARN, "TXTPEI::TPM is not present! Disabling TXT! TxtMode=%x\n", ctx.Hob->Data.TxtMode));
+ }
+
+ TxtEnvInitFail = TRUE;
+ }
+ ///
+ /// Detect TXT capable Processor & PCH
+ ///
+ if (!IsTxtChipset (&ctx)) {
+ DEBUG ((EFI_D_WARN, "TXTPEI::Platform or PCH is not TXT capable\n"));
+ return EFI_UNSUPPORTED;
+ } else if (!IsTxtProcessor ()) {
+ DEBUG ((EFI_D_WARN, "TXTPEI::Processor is not TXT capable\n"));
+ return EFI_UNSUPPORTED;
+ } else {
+ DEBUG ((EFI_D_WARN, "TXTPEI::Processor, PCH & Platform is TXT capable\n"));
+ ///
+ /// If Txt Lib or TPM is initiated successful, disable TxT support.
+ ///
+ if (TxtEnvInitFail) {
+ UnlockMemory (&ctx);
+ ctx.Hob->Data.TxtMode = 0;
+ ASSERT (TRUE);
+ return EFI_UNSUPPORTED;
+ }
+ }
+ ///
+ /// Memory is supposed to lock if system is TxT capable.
+ /// Check if we need to run SCLEAN. TxT BIOS spec Section 6.2.5
+ ///
+ if (IsEstablishmentBitAsserted (&ctx) && IsTxtWakeError (&ctx)) {
+
+ DEBUG ((EFI_D_INFO, "TXTPEI::EstablishmentBit is set\n"));
+ ///
+ /// If TXTRESET is set , we must clean TXTRESET bit otherwise SCLEAN
+ /// will fail
+ ///
+ if (IsTxtResetSet (&ctx)) {
+ DoGlobalReset ();
+ }
+ ///
+ /// Setup and Launch SCLEAN
+ ///
+ DEBUG ((EFI_D_INFO, "TXTPEI::Entering SCLEAN\n"));
+
+ DoSclean (&ctx);
+
+ ///
+ /// Reset platform - performed by DoSclean, should not return to execute the following dead looping
+ ///
+ EFI_DEADLOOP ();
+ } else {
+ ///
+ /// Unlock memory, and then continue running
+ ///
+ DEBUG ((EFI_D_INFO, "TXTPEI::EstablishmentBit not asserted - Unlock Memory\n"));
+ AsmWriteMsr64 (0x2e6, 0);
+ }
+
+ Status = PeiServicesNotifyPpi (&mNotifyDesc);
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Fix up pointers since they are located in real memory now.
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] NotifyDescriptor The notification structure this PEIM registered on install.
+ @param[in] Ppi The memory discovered PPI. Not used.
+
+ @retval EFI_SUCCESS The function completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+DprUpdate (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ TXT_INFO_HOB *TxtInfoHob;
+ SA_DATA_HOB *SaDataHob;
+ DPR_DIRECTORY_ENTRY *DprDirectory;
+ UINT16 Index;
+
+ TxtInfoHob = NULL;
+ SaDataHob = NULL;
+ DprDirectory = NULL;
+ Index = 0;
+
+ //
+ // Get TxtInfoHob
+ //
+ TxtInfoHob = (TXT_INFO_HOB *)GetFirstGuidHob (&gTxtInfoHobGuid);
+ if (TxtInfoHob == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ TxtInfoHob->Data.TxtDprMemoryBase = 0;
+
+ //
+ // Get SaDataHob
+ //
+ SaDataHob = (SA_DATA_HOB *)GetFirstGuidHob (&gSaDataHobGuid);
+ if (SaDataHob == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ DprDirectory = (DPR_DIRECTORY_ENTRY *)&(SaDataHob->DprDirectory[0]);
+
+ //
+ // Find TxT DPR Directory
+ //
+ for (Index=0; Index<DPR_DIRECTORY_MAX; Index++) {
+ if (DprDirectory[Index].Type == DPR_DIRECTORY_TYPE_TXT) {
+ TxtInfoHob->Data.TxtDprMemoryBase = (EFI_PHYSICAL_ADDRESS)DprDirectory[Index].PhysBase;
+ break;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.dxs b/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.dxs
new file mode 100644
index 0000000..fa940d7
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.dxs
@@ -0,0 +1,49 @@
+/** @file
+ This is the Dependency expression for the TXT Pei PPI
+
+@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
+
+**/
+
+
+//
+// Common for R8 and R9 codebase
+//
+#include "AutoGen.h"
+#include "DxeDepex.h"
+
+//
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are both "defined" in R8 codebase;
+// BUILD_WITH_EDKII_GLUE_LIB is defined in Edk-Dev-Snapshot-20070228 and later version
+// BUILD_WITH_GLUELIB and BUILD_WITH_EDKII_GLUE_LIB are "not defined" in R9 codebase.
+//
+#if defined (BUILD_WITH_GLUELIB) || defined (BUILD_WITH_EDKII_GLUE_LIB)
+#include "EfiDepex.h"
+#include EFI_PPI_DEFINITION (Stall)
+#include EFI_PPI_CONSUMER (BootMode)
+#endif
+
+#include EFI_PPI_DEFINITION (TpmInitialized)
+#include EFI_PPI_DEFINITION (CpuPlatformPolicy)
+#include EFI_PPI_DEPENDENCY (SaPeiInit)
+
+DEPENDENCY_START
+ PEI_STALL_PPI_GUID AND
+ PEI_MASTER_BOOT_MODE_PEIM_PPI AND
+ PEI_CPU_PLATFORM_POLICY_PPI_GUID AND
+ SA_PEI_INIT_PPI_GUID
+DEPENDENCY_END
+
diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.inf b/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.inf
new file mode 100644
index 0000000..428372a
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.inf
@@ -0,0 +1,104 @@
+## @file
+# Component description file for TXT PEI module
+#
+#@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
+#
+
+[defines]
+BASE_NAME = TxtPei
+FILE_GUID = CA9D8617-D652-403b-B6C5-BA47570116AD
+COMPONENT_TYPE = PE32_PEIM
+
+[sources.common]
+ TxtPei.c
+ TxtPeiLib.c
+ Ia32/TxtPeiBsp.asm
+
+#
+# Edk II Glue Driver Entry Point
+#
+ EdkIIGluePeimEntryPoint.c
+
+[includes.common]
+ .
+ $(EFI_SOURCE)/$(PROJECT_SA_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_SA_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/Include/Library
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Cpu/Pentium/Include
+ $(EDK_SOURCE)/Foundation/Framework/Ppi/Stall
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+
+#
+# Edk II Glue Library, some hearder are included by R9 header so have to include
+#
+
+ $(EFI_SOURCE)
+ $(EFI_SOURCE)/Framework
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Include/Pei
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+#
+# Typically the sample code referenced will be available in the code base already
+# So keep this include at the end to defer to the source base definition
+# and only use the sample code definition if source base does not include these files.
+#
+ $(EFI_SOURCE)/$(PROJECT_CPU_ROOT)/SampleCode
+
+[libraries.common]
+ EdkFrameworkPpiLib
+ SaGuidLib
+ CpuPpiLib
+ CpuGuidLib
+ EdkIIGlueBaseIoLibIntrinsic
+ EdkIIGlueBaseLib
+ EdkIIGlueBaseMemoryLib
+ EdkIIGlueBasePciLibPciExpress
+ EdkIIGluePeiDebugLibReportStatusCode
+ EdkIIGluePeiReportStatusCodeLib
+ EdkIIGluePeiServicesLib
+ EdkIIGluePeiMemoryAllocationLib
+ EdkIIGluePeiHobLib
+ AnchorCoveLib
+ TxtLib
+
+[nmake.common]
+ IMAGE_ENTRY_POINT = _ModuleEntryPoint
+ DPX_SOURCE = TxtPei.dxs
+#
+# Module Entry Point
+#
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=PeimEntry
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ -D __EDKII_GLUE_BASE_LIB__ \
+ -D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ -D __EDKII_GLUE_PEI_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ -D __EDKII_GLUE_PEI_REPORT_STATUS_CODE_LIB__ \
+ -D __EDKII_GLUE_PEI_SERVICES_LIB__
diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.mak b/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.mak
new file mode 100644
index 0000000..ecb55ef
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.mak
@@ -0,0 +1,105 @@
+# MAK file for the ModulePart:TxtPei
+
+all : TxtPei
+
+TxtPei : $(BUILD_DIR)\TxtPei.mak TxtPeiBin TxtPeiAp.bin $(BUILD_DIR)\TxtPeiap.ffs
+
+$(BUILD_DIR)\TxtPei.mak : $(TxtPei_DIR)\$(@B).cif $(TxtPei_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(TxtPei_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+MY_DEFINES=\
+ /DAMI_MICROCODE_PPI\
+!IF "$(TXT_DEBUG_INFO)"=="1"
+ /D"TXT_DEBUG_INFO=1"\
+!ELSE
+ /D"TXT_DEBUG_INFO=0"\
+!ENDIF
+
+TxtPei_INCLUDES=\
+ $(EDK_INCLUDES)\
+ $(EdkIIGlueLib_INCLUDES)\
+ $(TXT_INCLUDES)\
+ $(PROJECT_CPU_INCLUDES)\
+ $(PROJECT_INCLUDES)\
+ $(INTEL_MCH_INCLUDES)\
+ $(TCG_INCLUDES)\
+
+TxtPei_DEFINES=\
+ $(MY_DEFINES)\
+ /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=PeimEntry"\
+ /D PlatformPciExpressBaseAddress=$(PCIEX_BASE_ADDRESS) \
+ /D __EDKII_GLUE_BASE_IO_LIB_INTRINSIC__ \
+ /D __EDKII_GLUE_BASE_LIB__ \
+ /D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ /D __EDKII_GLUE_PEI_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ /D __EDKII_GLUE_PEI_REPORT_STATUS_CODE_LIB__ \
+ /D __EDKII_GLUE_PEI_SERVICES_LIB__\
+ /D __EDKII_GLUE_PEI_SERVICES_TABLE_POINTER_LIB_MM7__ \
+
+TxtPei_OBJECTS=\
+ $(BUILD_DIR)\$(TxtPei_DIR)\TxtPei.obj\
+ $(BUILD_DIR)\$(TxtPei_DIR)\TxtPeiLib.obj\
+ $(BUILD_DIR)\$(TxtPei_DIR)\Ia32\TxtPeiBsp.obj
+
+TxtPei_LIBS=\
+ $(EDKFRAMEWORKPPILIB)\
+ $(EdkIIGlueBaseIoLibIntrinsic_LIB)\
+ $(BUILD_DIR)\IA32\EdkIIGlueBaseLib.lib\
+ $(EdkIIGlueBaseMemoryLib_LIB)\
+ $(EdkIIGluePeiDxeDebugLibReportStatusCode_LIB)\
+ $(EdkIIGluePeiReportStatusCodeLib_LIB)\
+ $(EdkIIGluePeiDebugLibReportStatusCode_LIB)\
+ $(EdkIIGluePeiServicesLib_LIB)\
+ $(EdkIIGluePeiHobLib_LIB)\
+ $(EdkIIGluePeiMemoryAllocationLib_LIB)\
+ $(CpuGuidLib_LIB)\
+ $(CPU_PPI_LIB)\
+ $(SaGuidLib_LIB)\
+ $(PEIHOBLIB)\
+ $(EdkIIGlueBasePciLibPciExpress_LIB)\
+ $(EdkIIGlueBasePciExpressLib_LIB)\
+ $(PchPlatformPeiLib_LIB)\
+ $(CpuPlatformLib_LIB)\
+ $(BootGuardLib_LIB)\
+ $(TxtLib_LIB)
+
+TxtPeiBin : $(TxtPei_LIBS)
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\TxtPei.mak all\
+ "MY_INCLUDES=$(TxtPei_INCLUDES)"\
+ "MY_DEFINES=$(TxtPei_DEFINES)"\
+ "OBJECTS=$(TxtPei_OBJECTS)" \
+ "AFLAGS=$(AFLAGS) $(PROJECT_CPU_INCLUDES)"\
+ GUID=CA9D8617-D652-403b-B6C5-BA47570116AD\
+ ENTRY_POINT=_ModuleEntryPoint\
+ TYPE=PEIM \
+ EDKIIModule=PEIM\
+ DEPEX1=$(TxtPei_DIR)\TxtPei.dxs \
+ DEPEX1_TYPE=EFI_SECTION_PEI_DEPEX \
+ COMPRESS=0\
+
+TxtPeiAp.bin: $(BUILD_DIR)\TxtPeiap.bin
+
+$(BUILD_DIR)\TxtPeiap.bin: $(BUILD_DIR)\TxtPeiAp.obj
+
+$(BUILD_DIR)\TxtPeiAp.obj:$(TxtPei_DIR)\Ia32\TxtPeiAp.asm16
+ $(ASM) /c /nologo $(PROJECT_CPU_INCLUDES) /Fo$(BUILD_DIR)\TxtPeiAp.obj $(TxtPei_DIR)\Ia32\TxtPeiAp.asm16
+ $(ASMLINK) $(BUILD_DIR)\TxtPeiAp.obj, $*.exe, $*.map,,,
+ exe2bin $*.exe $*.bin
+
+$(BUILD_DIR)\TxtPeiap.ffs : $(BUILD_DIR)\TxtPeiap.bin
+ $(MAKE) /f Core\FFS.mak \
+ BUILD_DIR=$(BUILD_DIR) \
+ GUID=$(AP_GUID) \
+ TYPE=EFI_FV_FILETYPE_RAW \
+ FFS_CHECKSUM=0 \
+ FFS_ALIGNMENT=5 \
+ RAWFILE=$(BUILD_DIR)\TxtPeiap.bin \
+ COMPRESS=0 \
+ FFSFILE=$@ \
+ NAME=DummyName
+
+TXT_AP_FIXUP:
+ $(TxtTools_DIR)\STAFixup.exe $(AP_GUID) $(AMI_ROM) $(AP_FIXUP_FILE) $(AP_OFFSET)
+
+AFTER_ROM: TXT_AP_FIXUP
diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.sdl b/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.sdl
new file mode 100644
index 0000000..b438250
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPei.sdl
@@ -0,0 +1,86 @@
+TOKEN
+ Name = "TxtPei_SUPPORT"
+ Value = "1"
+ Help = "Main switch to enable TXT Pei init support in Project"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ TargetH = Yes
+ Master = Yes
+End
+
+PATH
+ Name = "TxtPei_DIR"
+ Help = "TXT PEI source directory"
+End
+
+TOKEN
+ Name = "TXT_TOOL_DIR"
+ Value = "$(TXT_DIR)\Tools"
+ Help = "TXT tools directory"
+ TokenType = Expression
+ TargetMAK = Yes
+ TargetH = Yes
+END
+
+TOKEN
+ Name = "AP_GUID"
+ Value = "D1E59F50-E8C3-4545-BF61-11F002233C97"
+ Help = "GUID of AP initialization file."
+ TokenType = Expression
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "AP_FIXUP_FILE"
+ Value = "$(TXT_TOOL_DIR)\Apfixup.txt"
+ Help = "Name of AP FFS fixup table file."
+ TokenType = Expression
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+TOKEN
+ Name = "AP_OFFSET"
+ Value = "$(FV_BB_BLOCKS)*$(FLASH_BLOCK_SIZE)"
+ Help = "End-of-file offset of AP initialization file."
+ TokenType = Integer
+ TargetMAK = Yes
+ TargetH = Yes
+End
+
+MODULE
+ Help = "Includes TXTPEI.mak into project"
+ File = "TXTPEI.mak"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\txtpeiap.ffs"
+ Parent = "FV_BB"
+ Priority = -2000
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "TYPE:HOLE LOCATION:0xfffff000"
+ Parent = "$(BUILD_DIR)\txtpeiap.ffs"
+ InvokeOrder = AfterParent
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\TxtPei.ffs"
+ Parent = "FV_BB"
+ InvokeOrder = BeforeParent
+End
+
+ELINK
+ Name = "TXT_INCLUDES"
+ InvokeOrder = ReplaceParent
+End
+
+ELINK
+ Name = "/I$(TxtPei_DIR)"
+ Parent = "TXT_INCLUDES"
+ InvokeOrder = AfterParent
+End \ No newline at end of file
diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPeiLib.c b/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPeiLib.c
new file mode 100644
index 0000000..436ca18
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPeiLib.c
@@ -0,0 +1,1045 @@
+/** @file
+ This file contains an implementation of the function call interfaces
+ required by the main TXT PEIM file. Hopefully, future platform porting
+ tasks will be mostly limited to modifying the functions in this file.
+
+@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 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
+
+**/
+#include "TxtPeiLib.h"
+#include "TxtLibrary.h"
+
+EFI_GUID mTxtBiosAcmPeiFileGuid = PEI_BIOS_ACM_FILE_GUID;
+EFI_GUID mTxtApStartupPeiFileGuid = PEI_AP_STARTUP_FILE_GUID;
+EFI_GUID mCpuMicrocodeFileGuid = CPU_MICROCODE_FILE_GUID;
+#define EFI_PEI_PCI_CFG2_PPI_GUID \
+ { 0x57a449a, 0x1fdc, 0x4c06, 0xbf, 0xc9, 0xf5, 0x3f, 0x6a, 0x99, 0xbb, 0x92 }
+
+EFI_GUID gPeiPciCfgPpiInServiceTableGuid2 = EFI_PEI_PCI_CFG2_PPI_GUID;
+///
+/**
+ This routine initializes and collects all PPIs and data required
+ by the routines in this file.
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+ @param[in] mPS - A pointer to the PEI Service Table
+
+ @exception EFI_UNSUPPORTED - If any of the required PPIs or data are unavailable
+ @retval EFI_SUCCESS - In all cases not listed above
+**/
+EFI_STATUS
+InitializeTxtPeiLib (
+ IN TXT_PEI_LIB_CONTEXT *pctx,
+ IN EFI_PEI_SERVICES **mPS
+ )
+{
+ EFI_STATUS Status;
+
+ ///
+ /// Make sure our pointers start life as NULL pointers
+ ///
+ pctx->PeiStall = NULL;
+ pctx->BiosAcmBase = NULL;
+ pctx->ApStartup = NULL;
+ pctx->McuStart = NULL;
+
+ ///
+ /// Initialize all pointers
+ ///
+ pctx->PeiServices = mPS;
+ pctx->CpuIoPpi = (**mPS).CpuIo;
+
+ Status = PeiServicesLocatePpi (
+ &gPeiPciCfgPpiInServiceTableGuid2,
+ 0,
+ NULL,
+ (VOID **) &(pctx->PciCfgPpi)
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiStallPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &(pctx->PeiStall)
+ );
+
+ ASSERT_EFI_ERROR (Status);
+
+ ///
+ /// Find TxtInfoHob by platfrom code
+ ///
+ Status = CreateTxtInfoHob (pctx);
+
+ if (Status == EFI_NOT_FOUND) {
+ DEBUG ((EFI_D_ERROR, "TXTPEI: TXT Info Hob not found.\n"));
+ return EFI_UNSUPPORTED;
+ }
+ ///
+ /// Print out the TxtInfo HOB if TXT_DEBUG_INFO is set
+ ///
+ DEBUG ((EFI_D_INFO, "TXTPEI: TxtInfoHob passed from platform as:\n"));
+ DEBUG ((EFI_D_INFO, "TXTPEI: ChipsetIsTxtCapable = %x\n", pctx->Hob->Data.ChipsetIsTxtCapable));
+ DEBUG ((EFI_D_INFO, "TXTPEI: TxtMode = %x\n", pctx->Hob->Data.TxtMode));
+ DEBUG ((EFI_D_INFO, "TXTPEI: PmBase = %x\n", pctx->Hob->Data.PmBase));
+ DEBUG ((EFI_D_INFO, "TXTPEI: SinitMemorySize = %x\n", pctx->Hob->Data.SinitMemorySize));
+ DEBUG ((EFI_D_INFO, "TXTPEI: TxtHeapMemorySize = %x\n", pctx->Hob->Data.TxtHeapMemorySize));
+ DEBUG ((EFI_D_INFO, "TXTPEI: TxtDprMemoryBase = %x\n", pctx->Hob->Data.TxtDprMemoryBase));
+ DEBUG ((EFI_D_INFO, "TXTPEI: TxtDprMemorySize = %x\n", pctx->Hob->Data.TxtDprMemorySize));
+ DEBUG ((EFI_D_INFO, "TXTPEI: BiosAcmBase = %x\n", pctx->Hob->Data.BiosAcmBase));
+ DEBUG ((EFI_D_INFO, "TXTPEI: BiosAcmSize = %x\n", pctx->Hob->Data.BiosAcmSize));
+ DEBUG ((EFI_D_INFO, "TXTPEI: McuUpdateDataAddr = %x\n", pctx->Hob->Data.McuUpdateDataAddr));
+ DEBUG ((EFI_D_INFO, "TXTPEI: SinitAcmBase = %x\n", pctx->Hob->Data.SinitAcmBase));
+ DEBUG ((EFI_D_INFO, "TXTPEI: SinitAcmSize = %x\n", pctx->Hob->Data.SinitAcmSize));
+ DEBUG ((EFI_D_INFO, "TXTPEI: TgaSize = %x\n", pctx->Hob->Data.TgaSize));
+ DEBUG ((EFI_D_INFO, "TXTPEI: TxtLcpPdBase = %x\n", pctx->Hob->Data.TxtLcpPdBase));
+ DEBUG ((EFI_D_INFO, "TXTPEI: TxtLcpPdSize = %x\n", pctx->Hob->Data.TxtLcpPdSize));
+ DEBUG ((EFI_D_INFO, "TXTPEI: Flags = %x\n", pctx->Hob->Data.Flags));
+
+ ///
+ /// Check if platform specify BIOS ACM addrss by itself, BIOS ACM address must be 4K alignment in FLASH address space
+ ///
+ if (pctx->Hob->Data.BiosAcmBase != 0) {
+ DEBUG ((EFI_D_INFO, "TXTPEI: Customized BIOS ACM location at %x\n", pctx->Hob->Data.BiosAcmBase));
+ ///
+ /// Check BIOS ACM is 4K alignment or not
+ ///
+ if ((pctx->Hob->Data.BiosAcmBase & 0xFFF) != 0) {
+ DEBUG ((EFI_D_ERROR, "TXTPEI: Customized BIOS ACM is not 4K aligned, force TxtMode=0 and unloaded!!\n"));
+ pctx->Hob->Data.TxtMode = 0;
+ return EFI_UNSUPPORTED;
+ }
+ ///
+ /// Get BIOS ACM base from TxtInfoHob provided by platform code
+ ///
+ pctx->BiosAcmBase = (ACM_HEADER *) (UINT32) pctx->Hob->Data.BiosAcmBase;
+ } else {
+ ///
+ /// Get BIOS ACM by seaching PEI firmware volume
+ ///
+ Status = FindBiosAcmInVolume (pctx, (UINT32 **) &pctx->BiosAcmBase);
+
+ ///
+ /// BIOS ACM not found, disable TXT and return EFI_UNLOAD_IMAGE
+ ///
+ if (((pctx->BiosAcmBase) == 0) || (Status == EFI_NOT_FOUND)) {
+ DEBUG ((EFI_D_ERROR, "TXTPEI: BIOS ACM not found, force TxtMode=0 and unloaded!\n"));
+ pctx->Hob->Data.TxtMode = 0;
+ return EFI_UNSUPPORTED;
+ }
+
+ DEBUG ((EFI_D_INFO, "TXTPEI: Found BIOS ACM location at %x\n", pctx->BiosAcmBase));
+
+ ///
+ /// Check BIOS ACM is 4K alignment, if not disable TXT and return EFI_UNLOAD_IMAGE
+ ///
+ if (((UINT32) pctx->BiosAcmBase & 0xFFF) != 0) {
+ DEBUG ((EFI_D_ERROR, "TXTPEI: BIOS ACM is not 4K aligned, force TxtMode=0 and unloaded!!\n"));
+ pctx->Hob->Data.TxtMode = 0;
+ return EFI_UNSUPPORTED;
+ }
+ }
+ ///
+ /// Check ACM is matched to chipset or not, if not, disable TXT and return EFI_UNLOAD_IMAGE
+ ///
+ if (!CheckTxtAcmMatch (pctx, pctx->BiosAcmBase)) {
+ DEBUG ((EFI_D_ERROR, "TXTPEI: BIOS ACM is not matched to chipset!! Force TxtMode=0 and unloaded!!\n"));
+ pctx->Hob->Data.TxtMode = 0;
+ return EFI_UNSUPPORTED;
+ }
+
+ pctx->BiosAcmSize = (pctx->BiosAcmBase->Size) << 2;
+
+ Status = FindApStartupInVolume (pctx, (UINT32 **) &(pctx->ApStartup));
+
+ if (Status == EFI_NOT_FOUND) {
+ DEBUG ((EFI_D_ERROR, "TXTPEI: AP Startup code not found.\n"));
+ pctx->Hob->Data.TxtMode = 0;
+ return EFI_UNSUPPORTED;
+ }
+
+ DEBUG ((EFI_D_INFO, "TXTPEI: Found AP init code at %x\n", pctx->ApStartup));
+
+ ///
+ /// Check if platform specify MCU addrss by itself
+ ///
+ if (pctx->Hob->Data.McuUpdateDataAddr != 0) {
+ DEBUG ((EFI_D_INFO, "Customized MCU location at %x\n", pctx->Hob->Data.McuUpdateDataAddr));
+ pctx->McuStart = (UINT32 *) (UINTN) pctx->Hob->Data.McuUpdateDataAddr;
+ } else {
+ ///
+ /// Find microcode update by searching PEI FV
+ ///
+ Status = FindMcuInVolume (pctx, (UINT32 **) &(pctx->McuStart));
+
+ if (Status == EFI_NOT_FOUND) {
+ DEBUG ((EFI_D_ERROR, "TXTPEI: MCU not found.\n"));
+ pctx->Hob->Data.TxtMode = 0;
+ return EFI_UNSUPPORTED;
+ }
+
+ DEBUG ((EFI_D_INFO, "TXTPEI: Found MCU at %x\n", pctx->McuStart));
+ }
+ ///
+ /// Initialize local APIC
+ ///
+ if ((((AsmReadMsr64 (MSR_IA32_APIC_BASE)) & (BIT11 + BIT10)) == BIT11 + BIT10)) {
+ AsmWriteMsr64 (EFI_MSR_EXT_XAPIC_SVR, 0x1FF);
+ } else {
+ ///
+ /// Determine address of Local APIC
+ ///
+ pctx->Ia32ApicBase = ((UINT32) AsmReadMsr64 (MSR_IA32_APIC_BASE)) & BASE_ADDR_MASK;
+ *(UINT32 *) (pctx->Ia32ApicBase + APIC_SPURIOUS_VECTOR_REGISTER) = 0x1FF;
+ }
+ ///
+ /// Initialize TxtInfoHob fields
+ ///
+ pctx->Hob->Data.BiosAcmBase = (UINTN) pctx->BiosAcmBase;
+ pctx->Hob->Data.BiosAcmSize = (UINTN) pctx->BiosAcmSize;
+ pctx->Hob->Data.McuUpdateDataAddr = (UINTN) pctx->McuStart;
+
+ ///
+ /// Make sure none of our pointers are still NULL
+ ///
+ if (!(pctx->PeiStall && pctx->BiosAcmBase && pctx->ApStartup && pctx->McuStart)) {
+ pctx->Hob->Data.TxtMode = 0;
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Determines whether or not the current processor is TXT Capable.
+
+ @retval TRUE - If the current processor supports TXT
+ @retval FALSE - If the current processor does not support TXT
+**/
+BOOLEAN
+IsTxtProcessor (
+ VOID
+ )
+{
+ EFI_CPUID_REGISTER CpuidRegs;
+
+ AsmCpuid (1, &CpuidRegs.RegEax, &CpuidRegs.RegEbx, &CpuidRegs.RegEcx, &CpuidRegs.RegEdx);
+
+ return (CpuidRegs.RegEcx & B_CPUID_VERSION_INFO_ECX_SME) ? TRUE : FALSE;
+}
+
+/**
+ Determines whether or not the current chipset is TXT Capable.
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval TRUE - If the current chipset supports TXT
+ @retval FALSE - If the current chipset doesn't supports TXT
+**/
+BOOLEAN
+IsTxtChipset (
+ IN TXT_PEI_LIB_CONTEXT *pctx
+ )
+{
+ BOOLEAN TxtCapable;
+ UINT32 Data32;
+
+ TxtCapable = FALSE;
+ Data32 = CheckSmxCapabilities();
+
+ if ((Data32 & BIT0) != 0) {
+ TxtCapable = TRUE;
+ DEBUG ((EFI_D_INFO, "Platform/PCH - TXT supported\n"));
+ } else {
+ TxtCapable = FALSE;
+ DEBUG ((EFI_D_INFO, "Platform/PCH - TXT not supported!!!\n"));
+ }
+
+ return TxtCapable;
+}
+
+/**
+ Determines whether TXT is enabled by platform setting
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval TRUE - If TXT is enabled by platform setting
+ @retval FALSE - If TXT is disabled by platform setting
+**/
+BOOLEAN
+IsTxtEnabled (
+ IN TXT_PEI_LIB_CONTEXT *pctx
+ )
+{
+ if (pctx->Hob == 0) {
+ return FALSE;
+ }
+
+ return (BOOLEAN) (pctx->Hob->Data.TxtMode);
+}
+
+/**
+ Determines ACM is matched to chipset or not
+
+ @param[in] pctx - Point to TXT_PEI_LIB_CONTEXT structure
+ @param[in] BiosAcmBase - A pointer to BIOS ACM location
+
+ @retval TRUE - BIOS ACM is matched to chipset
+ @retval FALSE - BIOS ACM is NOT matched to chipset
+**/
+BOOLEAN
+CheckTxtAcmMatch (
+ IN TXT_PEI_LIB_CONTEXT *pctx,
+ IN ACM_HEADER *BiosAcmBase
+ )
+{
+ BOOLEAN ChipsetIsProduction;
+ BOOLEAN BiosAcmIsProduction;
+
+ if (BiosAcmBase == NULL) {
+ return FALSE;
+
+ }
+ ///
+ /// Initializing ChipsetIsProduction default value
+ ///
+ ChipsetIsProduction = (*(UINT32 *) (TXT_PUBLIC_BASE + 0x200) & BIT31) ? TRUE : FALSE;
+
+ ///
+ /// Check ACM is production or not
+ ///
+ BiosAcmIsProduction = (BiosAcmBase->ModuleID & BIT31) ? FALSE : TRUE;
+
+ return ChipsetIsProduction == BiosAcmIsProduction;
+}
+
+/**
+ Create TXT Info HOB
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval EFI_SUCCESS - If TXT Info Hob is found
+ @retval EFI_NOT_FOUND - If TXT Info Hob is not found
+**/
+EFI_STATUS
+CreateTxtInfoHob (
+ IN TXT_PEI_LIB_CONTEXT *pctx
+ )
+{
+ EFI_STATUS Status;
+ PEI_CPU_PLATFORM_POLICY_PPI *CpuPlatformPolicy;
+ TXT_INFO_HOB *TxtInfoHob;
+
+ TxtInfoHob = NULL;
+
+ ///
+ /// Locate TPM Initialized Ppi to determine TPM is present and initialized properly.
+ ///
+ Status = PeiServicesLocatePpi (
+ &gPeiCpuPlatformPolicyPpiGuid,
+ 0,
+ NULL,
+ (VOID **) &CpuPlatformPolicy
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ ///
+ /// Create hob for storing TXT data
+ ///
+ Status = (*(pctx->PeiServices))->CreateHob (
+ pctx->PeiServices,
+ EFI_HOB_TYPE_GUID_EXTENSION,
+ sizeof (TXT_INFO_HOB),
+ (VOID **) &TxtInfoHob
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ pctx->Hob = TxtInfoHob;
+ TxtInfoHob->EfiHobGuidType.Name = gTxtInfoHobGuid;
+
+ ///
+ /// Initiate Txt Info Hob
+ ///
+ ZeroMem (&(TxtInfoHob->Data), sizeof (TXT_INFO_DATA));
+
+ TxtInfoHob->Data.ChipsetIsTxtCapable = IsTxtChipset (pctx);
+ if (CpuPlatformPolicy->CpuConfig->Txt == 1) {
+ TxtInfoHob->Data.TxtMode = 1;
+ }
+ TxtInfoHob->Data.PmBase = MmioRead32 (
+ MmPciAddress (0,
+ PCI_BUS_NUMBER_PCH_LPC,
+ PCI_DEVICE_NUMBER_PCH_LPC,
+ PCI_FUNCTION_NUMBER_PCH_LPC,
+ R_PCH_LPC_ACPI_BASE)
+ ) &~1;
+
+ TxtInfoHob->Data.SinitMemorySize = CpuPlatformPolicy->SecurityConfig->TxtConfig->SinitMemorySize;
+ TxtInfoHob->Data.TxtHeapMemorySize = CpuPlatformPolicy->SecurityConfig->TxtConfig->TxtHeapMemorySize;
+ TxtInfoHob->Data.TxtDprMemoryBase = CpuPlatformPolicy->SecurityConfig->TxtConfig->TxtDprMemoryBase;
+ TxtInfoHob->Data.TxtDprMemorySize = CpuPlatformPolicy->SecurityConfig->TxtConfig->TxtDprMemorySize;
+ TxtInfoHob->Data.BiosAcmBase = CpuPlatformPolicy->SecurityConfig->TxtConfig->BiosAcmBase;
+ TxtInfoHob->Data.BiosAcmSize = CpuPlatformPolicy->SecurityConfig->TxtConfig->BiosAcmSize;
+ TxtInfoHob->Data.McuUpdateDataAddr = CpuPlatformPolicy->SecurityConfig->TxtConfig->McuUpdateDataAddr;
+ TxtInfoHob->Data.TgaSize = CpuPlatformPolicy->SecurityConfig->TxtConfig->TgaSize;
+ TxtInfoHob->Data.TxtLcpPdBase = CpuPlatformPolicy->SecurityConfig->TxtConfig->TxtLcpPdBase;
+ TxtInfoHob->Data.TxtLcpPdSize = CpuPlatformPolicy->SecurityConfig->TxtConfig->TxtLcpPdSize;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Determines whether or not the platform has executed an TXT launch by
+ examining the TPM Establishment bit.
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval TRUE - If the TPM establishment bit is asserted.
+ @retval FALSE - If the TPM establishment bit is unasserted.
+**/
+BOOLEAN
+IsEstablishmentBitAsserted (
+ IN TXT_PEI_LIB_CONTEXT *pctx
+ )
+{
+ UINT8 Access;
+ UINT16 TimeOutCount;
+
+ ///
+ /// Set TPM.ACCESS polling timeout about 750ms
+ ///
+ TimeOutCount = TPM_TIME_OUT;
+ do {
+ ///
+ /// Read TPM status register
+ ///
+
+ Access = pctx->CpuIoPpi->MemRead8 (
+ pctx->PeiServices,
+ pctx->CpuIoPpi,
+ TPM_STATUS_REG_ADDRESS
+ );
+
+ ///
+ /// if TPM.Access == 0xFF, TPM is not present
+ ///
+ if (Access == 0xFF) {
+ return FALSE;
+ }
+ ///
+ /// Check tpmRegValidSts bit before checking establishment bit
+ ///
+ if (((pctx->PeiStall) != NULL) && ((Access & 0x80) != 0x80)) {
+ ///
+ /// Delay 1ms
+ ///
+ pctx->PeiStall->Stall (pctx->PeiServices, pctx->PeiStall, 1000);
+ } else {
+ ///
+ /// tpmRegValidSts set, we can check establishment bit now.
+ ///
+ break;
+ }
+
+ TimeOutCount--;
+ } while (TimeOutCount != 0);
+ ///
+ /// if tpmRegValidSts is not set, TPM is not usable
+ ///
+ if ((Access & 0x80) != 0x80) {
+ DEBUG ((EFI_D_ERROR, "TXTPEI: TPM Valid Status is not set!! TPM.ACCESS=%x\n", Access));
+ ASSERT (TRUE);
+ EFI_DEADLOOP ();
+ }
+ ///
+ /// The bit we're interested in uses negative logic:
+ /// If bit 0 == 1 then return False
+ /// Else return True
+ ///
+ return (Access & 0x1) ? FALSE : TRUE;
+}
+
+/**
+ Determines whether or not the platform has encountered an error during
+ a sleep or power-off state.
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval TRUE - If the TXT_WAKE_ERROR bit is asserted.
+ @retval FALSE - If the TXT_WAKE_ERROR bit is unasserted.
+**/
+BOOLEAN
+IsTxtWakeError (
+ IN TXT_PEI_LIB_CONTEXT *pctx
+ )
+{
+ UINT8 Ests;
+
+ ///
+ /// Read TXT.ESTS register
+ ///
+ Ests = pctx->CpuIoPpi->MemRead8 (
+ pctx->PeiServices,
+ pctx->CpuIoPpi,
+ TXT_PUBLIC_BASE + TXT_ERROR_STATUS_REG_OFF
+ );
+
+ DEBUG ((EFI_D_INFO, "TXTPEI: TXT.ESTS=%x\n", Ests));
+
+ return (Ests & (0x1 << 6)) ? TRUE : FALSE;
+}
+
+/**
+ Determines whether or not the platform memory has been locked
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval TRUE - If memroy is locked
+ @retval FALSE - If memory is unlocked
+**/
+BOOLEAN
+IsMemoryLocked (
+ IN TXT_PEI_LIB_CONTEXT *pctx
+ )
+{
+ UINT32 CpuMemLockStatus;
+
+ ///
+ /// Check status register for now.
+ ///
+ CpuMemLockStatus = pctx->CpuIoPpi->MemRead32 (
+ pctx->PeiServices,
+ pctx->CpuIoPpi,
+ TXT_PUBLIC_BASE + TXT_E2STS_REG_OFF
+ );
+
+ DEBUG ((EFI_D_INFO, "TXTPEI: CPU_UNCORE_MEMLOCK_STATUS=%x\n", CpuMemLockStatus));
+ ///
+ /// if BLOCK_MEM_STS (BIT2) is set to 1, memory is in unlock.
+ ///
+ return (CpuMemLockStatus & TXT_BLOCK_MEM_STS) ? TRUE : FALSE;
+}
+
+/**
+ Determines whether or not POISON bit is set in status register
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval TRUE - If the TXT_WAKE_ERROR bit is asserted.
+ @retval FALSE - If the TXT_WAKE_ERROR bit is unasserted.
+**/
+BOOLEAN
+IsTxtResetSet (
+ IN TXT_PEI_LIB_CONTEXT *pctx
+ )
+{
+ UINT8 Ests;
+
+ ///
+ /// Read TXT.ESTS register
+ ///
+ Ests = pctx->CpuIoPpi->MemRead8 (
+ pctx->PeiServices,
+ pctx->CpuIoPpi,
+ TXT_PUBLIC_BASE + TXT_ERROR_STATUS_REG_OFF
+ );
+
+ return (Ests & (0x1 << 0)) ? TRUE : FALSE;
+}
+
+/**
+ Determines whether or not SECRETS.STS bit is set in E2STS status register
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval TRUE - If the LT.SECRETS.STS bit is asserted.
+ @retval FALSE - If the LT.SECRETS.STS bit is unasserted.
+**/
+BOOLEAN
+IsTxtSecretsSet (
+ IN TXT_PEI_LIB_CONTEXT *pctx
+ )
+{
+ UINT8 E2sts;
+
+ ///
+ /// Read TXT.E2STS register
+ ///
+ E2sts = pctx->CpuIoPpi->MemRead8 (
+ pctx->PeiServices,
+ pctx->CpuIoPpi,
+ TXT_PUBLIC_BASE + TXT_E2STS_REG_OFF
+ );
+
+ return (E2sts & TXT_SECRETS_STS) ? TRUE : FALSE;
+}
+
+/**
+ Determines presence of TPM in system
+
+ @param[in] pctx - Point to TXT_PEI_LIB_CONTEXT structure
+ @param[in] TxtPeiCtx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval EFI_SUCCESS - If the TPM is present.
+ @retval EFI_NOT_FOUND - If the TPM is not present.
+**/
+EFI_STATUS
+IsTpmPresent (
+ IN TXT_PEI_LIB_CONTEXT *pctx
+ )
+{
+ EFI_STATUS Status;
+ VOID *TpmInitialize;
+
+ ///
+ /// Locate TPM Initialized Ppi to determine TPM is present and initialized properly.
+ ///
+ Status = PeiServicesLocatePpi (
+ &gPeiTpmInitializedPpiGuid,
+ 0,
+ NULL,
+ &TpmInitialize
+ );
+ if (EFI_ERROR (Status)) {
+ ///
+ /// TPM initiated failed
+ ///
+ pctx->Hob->Data.Flags |= TPM_INIT_FAILED;
+ }
+
+ return Status;
+}
+
+/**
+ Clear Sleep Type register.
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval EFI_SUCCESS - Always
+**/
+EFI_STATUS
+ClearSlpTyp (
+ IN TXT_PEI_LIB_CONTEXT *pctx
+ )
+{
+ UINT32 Pm1Addr;
+ UINT32 Pm1Value;
+
+ ///
+ /// Make address for PM1_CNT
+ ///
+ Pm1Addr = ((UINT32) pctx->Hob->Data.PmBase) + 4;
+
+ ///
+ /// Read 32-bits from PM1_CNT
+ ///
+ Pm1Value = IoRead32 ((UINTN) Pm1Addr);
+
+ ///
+ /// Clear SLP_TYP bits 10-12
+ ///
+ Pm1Value = Pm1Value & 0xffffe3ff;
+ IoWrite32 (
+ (UINTN) Pm1Addr,
+ (UINT32) (Pm1Value)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Searches PEI firemare volume (FV_BB) for file containig BIOS ACM.
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+ @param[in] BiosAcBase - A pointer to pointer to variable to hold found address
+
+ @retval EFI_SUCCESS - If address has been found
+ @retval EFI_NOT_FOUND - If address has not been found
+**/
+EFI_STATUS
+FindBiosAcmInVolume (
+ IN TXT_PEI_LIB_CONTEXT *pctx,
+ OUT UINT32 **BiosAcBase
+ )
+{
+ EFI_STATUS Status;
+
+ Status = FindModuleInFlash (pctx, &mTxtBiosAcmPeiFileGuid, BiosAcBase);
+
+ ///
+ /// If BIOS ACM is not found - don't hang system. Assume that TXT
+ /// must be disabled.
+ ///
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ ASSERT (((((UINT32) (*BiosAcBase)) & 0xFFF) == 0) ? TRUE : FALSE);
+
+ return EFI_SUCCESS;
+
+}
+
+/**
+ Searches PEI firmware volume (FV_BB) for file containig AP Startup code
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+ @param[in] ApStartupBase - A pointer to pointer to variable to hold address
+
+ @retval EFI_SUCCESS - If address has been found
+ @retval EFI_NOT_FOUND - If address has not been found
+**/
+EFI_STATUS
+FindApStartupInVolume (
+ IN TXT_PEI_LIB_CONTEXT *pctx,
+ OUT UINT32 **ApStartupBase
+ )
+{
+ EFI_STATUS Status;
+ EFI_GUID PeiBiosApStartupFileGuid;
+ BOOLEAN GoodPlacement;
+
+ PeiBiosApStartupFileGuid = mTxtApStartupPeiFileGuid;
+ Status = FindModuleInFlash (pctx, &PeiBiosApStartupFileGuid, ApStartupBase);
+ ///
+ /// If AP Startup code is not found - don't hang system. Assume that TXT
+ /// must be disabled.
+ ///
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ ASSERT (((((UINT32) (*ApStartupBase)) & 0xFFF) == 0) ? TRUE : FALSE);
+
+ GoodPlacement = (BOOLEAN) (((UINT32) (*ApStartupBase) >= 0xFFFE0000) && ((UINT32) (*ApStartupBase) <= 0xFFFFF000));
+
+ ASSERT (GoodPlacement);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Searches PEI firmware volume (FV_BB) for offset of currently loaded MCU patch
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+ @param[in] McuBase - A pointer to pointer to variable to hold found offset
+ @param[in] address.
+
+ @retval EFI_SUCCESS - If address has been found
+ @retval EFI_NOT_FOUND - If address has not been found
+**/
+EFI_STATUS
+FindMcuInVolume (
+ IN TXT_PEI_LIB_CONTEXT *pctx,
+ OUT UINT32 **McuBase
+ )
+{
+ EFI_STATUS Status;
+ EFI_GUID MicrocodeGuid;
+ MSR_REGISTER Reg;
+ UINT32 PlatformId;
+ UINT32 McuRevision;
+ EFI_CPUID_REGISTER CpuidRegs;
+ MCU *McuAddr;
+ UINT8 *i;
+ UINT8 *j;
+ UINT8 *b;
+ UINT32 c;
+ //(AMI_CHG+)>
+ UINT32 MicroCodeFfsMaxSize;
+ EFI_FFS_FILE_HEADER *MicroCodeFfs;
+ UINT8 *McuFfsAddress;
+ MicroCodeFfs = NULL;
+ //<(AMI_CHG+)
+ McuAddr = NULL;
+
+ McuRevision = 0;
+ MicrocodeGuid = mCpuMicrocodeFileGuid;
+ Status = FindModuleInFlash (pctx, &MicrocodeGuid, (UINT32 **) &McuAddr);
+ ///
+ /// If MCU update is not found - don't hang system. Assume that TXT
+ /// must be disabled.
+ ///
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+ //(AMI_CHG+)>
+ McuFfsAddress = (UINT8 *) McuAddr;
+ MicroCodeFfs = (EFI_FFS_FILE_HEADER *)(McuFfsAddress - sizeof (EFI_FFS_FILE_HEADER));
+ MicroCodeFfsMaxSize = (UINT32)MicroCodeFfs->Size[2]*0x10000 + (UINT32)MicroCodeFfs->Size[1]*0x100 + (UINT32)MicroCodeFfs->Size[0];
+ DEBUG ((EFI_D_ERROR, "TXTPEI: MicroCodeFfsMaxSize = %X\n", MicroCodeFfsMaxSize));
+ //<(AMI_CHG+)
+ ///
+ /// MCU base address has been found. Find exact address of MCU
+ /// loaded in BSP
+ ///
+ Reg.Qword = AsmReadMsr64 (MSR_IA32_PLATFORM_ID);
+ PlatformId = (Reg.Dwords.High >> (PLATFORM_ID_SHIFT - 32)) & PLATFORM_ID_MASK;
+
+ AsmWriteMsr64 (MSR_IA32_BIOS_SIGN_ID, 0);
+
+ AsmCpuid (1, &CpuidRegs.RegEax, &CpuidRegs.RegEbx, &CpuidRegs.RegEcx, &CpuidRegs.RegEdx);
+
+ Reg.Qword = AsmReadMsr64 (MSR_IA32_BIOS_SIGN_ID);
+
+ McuRevision = Reg.Dwords.High;
+
+ ///
+ /// if BSP MCU is not loaded before. Return EFI_NOT_FOUND
+ /// This is pre-requisit.
+ ///
+ if (McuRevision == 0) {
+ DEBUG ((EFI_D_ERROR, "TXTPEI: BSP microcode is not loaded!! TXT aborted!\n"));
+ return EFI_NOT_FOUND;
+ }
+ //(AMI_CHG+)>
+ //for (i = (UINT8 *) McuAddr; i < ((UINT8 *) McuAddr) + 0x10000; i = i + 0x400) {
+ for (i = (UINT8 *) McuAddr; i < ((UINT8 *) McuAddr) + MicroCodeFfsMaxSize; i = i + 0x400) {
+ //<(AMI_CHG+)
+ if (((MCU *) i)->revision != McuRevision) {
+ continue;
+ }
+
+ if (!(((MCU *) i)->procFlags & (UINT32) LShiftU64 (1, PlatformId))) {
+ continue;
+ }
+
+ if ((((MCU *) i)->signature) == CpuidRegs.RegEax) {
+ *McuBase = (UINT32 *) i;
+ return EFI_SUCCESS;
+ }
+
+ if ((((MCU *) i)->dataSize) == 0) {
+ continue;
+ }
+
+ if ((((MCU *) i)->dataSize + sizeof (MCU)) >= (((MCU *) i)->totalSize)) {
+ continue;
+ }
+ ///
+ /// Extended signature table exists.
+ ///
+ b = i + (((MCU *) i)->dataSize);
+ ///
+ /// Base of EST table
+ ///
+ c = ((EST *) b)->count;
+ ///
+ /// Count of entries
+ ///
+ b += sizeof (EST);
+ ///
+ /// Base of PSS table entries
+ ///
+ for (j = b; j < b + (c * sizeof (PSS)); j = j + sizeof (PSS)) {
+ if ((((PSS *) j)->signature) == CpuidRegs.RegEax) {
+ *McuBase = (UINT32 *) i;
+ return EFI_SUCCESS;
+ }
+ }
+
+ continue;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Searches PEI firmware volume (FV_BB) for the file with specified GUID through pGuid
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+ @param[in] Guid - A pointer GUID
+ @param[in] Module - A pointer to pointer to variable to hold address
+
+ @retval EFI_SUCCESS - If address has been found
+ @retval EFI ERROR - If address has not been found
+**/
+EFI_STATUS
+FindModuleInFlash (
+ IN TXT_PEI_LIB_CONTEXT *pctx,
+ IN EFI_GUID *Guid,
+ OUT UINT32 **Module
+ )
+{
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
+ EFI_FFS_FILE_HEADER *FfsFile;
+ EFI_STATUS Status;
+ UINTN Instance;
+
+ Instance = BFV;
+
+ while (TRUE) {
+ Status = (*(pctx->PeiServices))->FfsFindNextVolume (pctx->PeiServices, Instance, &FvHeader);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ FfsFile = NULL;
+ ///
+ /// Start new search in volume
+ ///
+ while (TRUE) {
+ Status = (*(pctx->PeiServices))->FfsFindNextFile (pctx->PeiServices, EFI_FV_FILETYPE_RAW, FvHeader, &FfsFile);
+ if (Status == EFI_NOT_FOUND) {
+ break;
+ }
+
+ if (CompareGuid (&(FfsFile->Name), Guid)) {
+ *Module = (UINT32 *) ((UINT8 *) FfsFile + sizeof (EFI_FFS_FILE_HEADER));
+ return EFI_SUCCESS;
+ }
+ }
+
+ Instance += 1;
+ }
+}
+
+/**
+ Initializes values passed to AP
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+**/
+VOID
+PrepareApParams (
+ IN TXT_PEI_LIB_CONTEXT *pctx
+ )
+{
+ UINT32 TxtPublicSpace;
+
+ TxtPublicSpace = TXT_PUBLIC_BASE;
+
+ *(UINT32 *) (TxtPublicSpace + BIOACM_ADDR) = (UINT32) (pctx->BiosAcmBase);
+
+ *(UINT32 *) (TxtPublicSpace + MCU_BASE_ADDR) = (UINT32) (pctx->McuStart);
+
+ *(UINT32 *) (TxtPublicSpace + APINIT_ADDR) = (UINT32) (pctx->ApStartup);
+
+ *(UINT32 *) (TxtPublicSpace + SEMAPHORE) = 0;
+
+}
+
+/**
+ Returns CPU count
+
+ @retval Number of CPUs
+**/
+UINT32
+GetCpuCount (
+ VOID
+ )
+{
+ EFI_CPUID_REGISTER CpuidRegs;
+ AsmCpuid (1, &CpuidRegs.RegEax, &CpuidRegs.RegEbx, &CpuidRegs.RegEcx, &CpuidRegs.RegEdx);
+ return CpuidRegs.RegEbx >> 16;
+}
+
+/**
+ Invokes the SCLEAN function from the TXT BIOS ACM.
+ 1. Clearing of sleep type is necessary because SCLEAN destroys memory
+ context, so S3 after it is run and system is reset is impossible. We
+ do it here since there is no any indication that can sustain reset
+ for any other module to do it on our behalf.
+ 2. APs are initialized before calling of SCLEAN
+ 3. SCLEAN function is invoked.
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval EFI_SUCCESS - Always.
+**/
+EFI_STATUS
+DoSclean (
+ IN TXT_PEI_LIB_CONTEXT *pctx
+ )
+{
+ ClearSlpTyp (pctx);
+
+ PrepareApParams (pctx);
+#ifdef BOOT_GUARD_SUPPORT_FLAG
+#if BOOT_GUARD_SUPPORT_FLAG == 1
+ //
+ // Disable PBET before send IPI to APs
+ //
+ StopPbeTimer ();
+#endif
+#endif
+
+ LaunchBiosAcmSclean ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Unlock memory when security is set and TxT is not enabled
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval EFI_SUCCESS - Complete memory unlock
+ @exception EFI_UNSUPPORTED - CPU doesn't support TxT.
+**/
+EFI_STATUS
+UnlockMemory (
+ IN TXT_PEI_LIB_CONTEXT *pctx
+ )
+{
+ BOOLEAN EstablishmentBitAsserted;
+
+ EstablishmentBitAsserted = IsEstablishmentBitAsserted (pctx);
+
+ ///
+ /// Need to read FED40000 before unlocking memory
+ ///
+ if (!EstablishmentBitAsserted) {
+ DEBUG ((EFI_D_INFO, "TXTPEI::Unlock memory\n"));
+ AsmWriteMsr64 (0x2e6, 0);
+ } else {
+ ///
+ /// Lunch SCLEAN if wake error bit is set.
+ ///
+ if (IsTxtWakeError (pctx)) {
+ ///
+ /// If TXTRESET is set , we must clean TXTRESET bit otherwise SCLEAN
+ /// will fail
+ ///
+ if (IsTxtResetSet (pctx)) {
+ DoGlobalReset ();
+ }
+
+ if ((pctx->BiosAcmBase == 0) || (pctx->ApStartup == 0) || (pctx->McuStart == 0)) {
+ return EFI_UNSUPPORTED;
+ }
+ ///
+ /// Setup and Launch SCLEAN
+ ///
+ DEBUG ((EFI_D_INFO, "TXTPEI::Entering SCLEAN to unlock memory\n"));
+ DoSclean (pctx);
+
+ ///
+ /// Reset platform - performed by DoSclean, should not return to execute the following dead looping
+ ///
+ EFI_DEADLOOP ();
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPeiLib.h b/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPeiLib.h
new file mode 100644
index 0000000..28c1303
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/TxtInit/Pei/TxtPeiLib.h
@@ -0,0 +1,560 @@
+/** @file
+ This file contains function definitions that can determine
+ the TXT capabilities of a platform during PEI and perform
+ certain specific platform tasks that are required for TXT
+ during PEI.
+
+@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 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
+
+**/
+#ifndef _TXT_PEI_LIB_H_
+#define _TXT_PEI_LIB_H_
+
+
+///
+/// External include files do NOT need to be explicitly specified in real EDKII
+/// environment
+///
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGluePeim.h"
+#include "Txt.h"
+#include "CpuAccess.h"
+#include "BootGuardLibrary.h"
+
+#include EFI_PPI_DEPENDENCY (Variable)
+#include EFI_PPI_DEPENDENCY (Stall)
+#include EFI_PPI_DEFINITION (TxtMemoryUnlocked)
+#include EFI_GUID_DEFINITION (TxtInfoHob)
+#include EFI_PPI_PRODUCER (CpuPlatformPolicy)
+#endif
+#include EFI_PPI_CONSUMER (TpmInitialized)
+
+#define RESET_PORT 0x0CF9
+#define FULL_RESET_VALUE 0xE
+
+#define PCI_BUS_NUMBER_PCH_LPC 0
+#define PCI_DEVICE_NUMBER_PCH_LPC 31
+#define PCI_FUNCTION_NUMBER_PCH_LPC 0
+#define R_PCH_LPC_ACPI_BASE 0x40
+
+#define APIC_SPURIOUS_VECTOR_REGISTER 0xF0
+#define DEST_FIELD (0 << 18)
+#define ALL_EXCLUDING_SELF BIT19 + BIT18
+#define SIPI BIT10 + BIT9
+#define INIT BIT10 + BIT8
+#define LEVEL_ASSERT BIT14
+#define LEVEL_DEASSERT (0 << 14)
+#define DELIVERY_STATUS BIT13
+#define BASE_ADDR_MASK 0xFFFFF000
+///
+/// #define EFI_MSR_EXT_XAPIC_LVT_THERM 0x833
+///
+#define EFI_MSR_EXT_XAPIC_SVR 0x80F
+#define AP_STARTUP_SIZE 0x1000
+#define AP_STARTUP_ADDR 0x1000
+#define AP_STARTUP_STKOFF AP_STARTUP_ADDR + 0xFF0
+
+#define BFV 0 ///< Boot Firmware Voume
+#define PCI_CMD 0x0004 ///< PCI Command Register
+#define BM_BIT 0x4 ///< Bus Master bit
+#define PCI_SCC 0x000A ///< Sub Class Code Register
+#define PCI_HDR 0x000E ///< Header Type Register
+#define MF_BIT 0x80 ///< Multi-function bit
+///
+/// Machne check architecture MSR registers
+///
+#define MCG_CAP 0x179
+#define MCG_STATUS 0x17A
+#define MCG_CTL 0x17B
+#define MC0_CTL 0x400
+#define MC0_STATUS 0x401
+#define MC0_ADDR 0x402
+#define MC0_MISC 0x403
+
+typedef struct _ACM_HEADER {
+ UINT32 ModuleType; ///< Module type
+ UINT32 HeaderLen; ///< 4 4 Header length (in multiples of four bytes)
+ /// (161 for version 0.0)
+ ///
+ UINT32 HeaderVersion; ///< 8 4 Module format version
+ UINT32 ModuleID; ///< 12 4 Module release identifier
+ UINT32 ModuleVendor; ///< 16 4 Module vendor identifier
+ UINT32 Date; ///< 20 4 Creation date (BCD format:
+ /// year.month.day)
+ ///
+ UINT32 Size; ///< 24 4 Module size (in multiples of four bytes)
+ UINT32 Reserved1; ///< 28 4 Reserved for future extensions
+ UINT32 CodeControl; ///< 32 4 Authenticated code control flags
+ UINT32 ErrorEntryPoint; ///< 36 4 Error response entry point offset (bytes)
+ UINT32 GDTLimit; ///< 40 4 GDT limit (defines last byte of GDT)
+ UINT32 GDTBasePtr; ///< 44 4 GDT base pointer offset (bytes)
+ UINT32 SegSel; ///< 48 4 Segment selector initializer
+ UINT32 EntryPoint; ///< 52 4 Authenticated code entry point offset (bytes)
+ UINT32 Reserved2; ///< 56 64 Reserved for future extensions
+ UINT32 KeySize; ///< 120 4 Module public key size less the exponent
+ /// (in multiples of four bytes
+ /// - 64 for version 0.0)
+ ///
+ UINT32 ScratchSize; ///< 124 4 Scratch field size (in multiples of four bytes)
+ /// (2 * KeySize + 15 for version 0.0)
+ ///
+ UINT8 RSAPubKey[65 * 4]; ///< 128 KeySize * 4 + 4 Module public key
+ UINT8 RSASig[256]; ///< 388 256 PKCS #1.5 RSA Signature.
+} ACM_HEADER;
+
+typedef struct _TXT_PEI_LIB_CONTEXT {
+ EFI_PEI_SERVICES **PeiServices;
+ PEI_CPU_IO_PPI *CpuIoPpi;
+ PEI_PCI_CFG_PPI *PciCfgPpi;
+ PEI_STALL_PPI *PeiStall;
+ ACM_HEADER *BiosAcmBase;
+ UINT32 BiosAcmSize;
+ VOID *ApStartup;
+ UINT32 *McuStart;
+ UINT32 Ia32ApicBase;
+ TXT_INFO_HOB *Hob;
+} TXT_PEI_LIB_CONTEXT;
+
+#pragma pack(1)
+typedef union _MSR_REGISTER {
+ UINT64 Qword;
+
+ struct _DWORDS {
+ UINT32 Low;
+ UINT32 High;
+ } Dwords;
+
+ struct _BYTES {
+ UINT8 FirstByte;
+ UINT8 SecondByte;
+ UINT8 ThirdByte;
+ UINT8 FouthByte;
+ UINT8 FifthByte;
+ UINT8 SixthByte;
+ UINT8 SeventhByte;
+ UINT8 EighthByte;
+ } Bytes;
+
+} MSR_REGISTER;
+
+
+#pragma pack()
+
+#define PLATFORM_ID_SHIFT 50
+#define PLATFORM_ID_MASK 7 ///< Bits 52:50
+typedef struct _MCU {
+ UINT32 headerVer; ///< MCU Header Version ( = 00000001h )
+ UINT32 revision; ///< MCU Revision
+ UINT32 date; ///< MCU Date
+ UINT32 signature; ///< MCU Processor Signature
+ UINT32 checksum; ///< MCU Main checksum
+ UINT32 loaderRev; ///< MCU Loader Revision
+ UINT32 procFlags; ///< MCU Processor Flags (Platform ID)
+ UINT32 dataSize; ///< MCU Data Size
+ UINT32 totalSize; ///< MCU Total Size
+ UINT32 reserved[3];
+} MCU;
+
+typedef struct _EST {
+ UINT32 count; ///< EST Count
+ UINT32 checksum; ///< EST Checksum
+ UINT32 reserved[3];
+} EST;
+
+typedef struct _PSS {
+ UINT32 signature; ///< PSS Processor Signature
+ UINT32 procFlags; ///< PSS Processor Flags (Platform ID)
+ UINT32 checksum; ///< PSS Checksum
+} PSS;
+
+/**
+ Returns CPU count
+
+ @retval Number of CPUs
+**/
+UINT32
+GetCpuCount (
+ VOID
+ );
+
+/**
+ Execute SCLEAN through BIOS ACM
+**/
+VOID
+LaunchBiosAcmSclean (
+ VOID
+ );
+
+/**
+ Issue a global reset through PCH and PORTCF9
+**/
+VOID
+DoGlobalReset (
+ VOID
+ );
+
+/**
+ Issue a cpu-only reset through PCH and PORTCF9
+**/
+VOID
+DoCpuReset (
+ VOID
+ );
+
+/**
+ Issue a HOST reset through PCH and PORTCF9
+**/
+VOID
+DoHostReset (
+ VOID
+ );
+
+/**
+ Dispatch APs to execute *Function with parameter pointed by *Param
+
+ @param[in] (*Function) - Address of Function to be executed by APs
+ @param[in] Param - Function parameter to be passed to
+**/
+VOID
+StartupAllAPs (
+ VOID (*Function)(),
+ UINT64 *Param
+ );
+
+/**
+ Put All APs into Wait-for-SIPI state
+**/
+VOID
+PutApsInWfs (
+ VOID
+ );
+
+/**
+ Restore MTRR registers
+
+ @param[in] ApCfg - Point to the MTRR buffer
+**/
+VOID
+RestoreMtrrProgramming (
+ UINT64 *ApCfg
+ );
+
+/**
+ Restore APs' registers
+
+ @param[in] ApCfg - Point to APs' registers buffer
+**/
+VOID
+RestoreApConfig (
+ UINT64 *ApCfg
+ );
+
+/**
+ Initializes values passed to AP
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+**/
+VOID
+PrepareApParams (
+ TXT_PEI_LIB_CONTEXT *pctx
+ );
+
+/**
+ This routine initializes and collects all PPIs and data required
+ by the routines in this file.
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+ @param[in] mPS - A pointer to the PEI Service Table
+
+ @exception EFI_UNSUPPORTED - If any of the required PPIs or data are unavailable
+ @retval EFI_SUCCESS - In all cases not listed above
+**/
+EFI_STATUS
+InitializeTxtPeiLib (
+ TXT_PEI_LIB_CONTEXT *pctx,
+ IN EFI_PEI_SERVICES **mPS
+ );
+
+/**
+ Determines whether or not the current processor is TXT Capable.
+
+ @retval TRUE - If the current processor supports TXT
+ @retval FALSE - If the current processor does not support TXT
+**/
+BOOLEAN
+IsTxtProcessor (
+ VOID
+ );
+
+/**
+ Determines whether or not the current chipset is TXT Capable.
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval TRUE - If the current chipset supports TXT
+ @retval FALSE - If the current chipset doesn't supports TXT
+**/
+BOOLEAN
+IsTxtChipset (
+ TXT_PEI_LIB_CONTEXT *pctx
+ );
+
+/**
+ Determines whether or not POISON bit is set in status register
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval TRUE - If the TXT_WAKE_ERROR bit is asserted.
+ @retval FALSE - If the TXT_WAKE_ERROR bit is unasserted.
+**/
+BOOLEAN
+IsTxtResetSet (
+ TXT_PEI_LIB_CONTEXT *pctx
+ );
+
+/**
+ Determines whether or not SECRETS.STS bit is set in E2STS status register
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval TRUE - If the LT.SECRETS.STS bit is asserted.
+ @retval FALSE - If the LT.SECRETS.STS bit is unasserted.
+**/
+BOOLEAN
+IsTxtSecretsSet (
+ TXT_PEI_LIB_CONTEXT *pctx
+ );
+
+/**
+ Determines whether or not the platform has executed an TXT launch by
+ examining the TPM Establishment bit.
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval TRUE - If the TPM establishment bit is asserted.
+ @retval FALSE - If the TPM establishment bit is unasserted.
+**/
+BOOLEAN
+IsEstablishmentBitAsserted (
+ IN TXT_PEI_LIB_CONTEXT *pctx
+ );
+
+/**
+ Determines whether or not the platform has encountered an error during
+ a sleep or power-off state.
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval TRUE - If the TXT_WAKE_ERROR bit is asserted.
+ @retval FALSE - If the TXT_WAKE_ERROR bit is unasserted.
+**/
+BOOLEAN
+IsTxtWakeError (
+ TXT_PEI_LIB_CONTEXT *pctx
+ );
+
+/**
+ Determines whether or not the platform memory has been locked
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval TRUE - If memroy is locked
+ @retval FALSE - If memory is unlocked
+**/
+BOOLEAN
+IsMemoryLocked (
+ TXT_PEI_LIB_CONTEXT *pctx
+ );
+
+/**
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval TRUE - If TXT is enabled by platform setting
+ @retval FALSE - If TXT is disabled by platform setting
+**/
+BOOLEAN
+IsTxtEnabled (
+ TXT_PEI_LIB_CONTEXT *pctx
+ );
+
+/**
+ Determines ACM is matched to chipset or not
+
+ @param[in] pctx - Point to TXT_PEI_LIB_CONTEXT structure
+ @param[in] BiosAcmBase - A pointer to BIOS ACM location
+
+ @retval TRUE - BIOS ACM is matched to chipset
+ @retval FALSE - BIOS ACM is NOT matched to chipset
+**/
+BOOLEAN
+CheckTxtAcmMatch (
+ TXT_PEI_LIB_CONTEXT *pctx,
+ ACM_HEADER *BiosAcmBase
+ );
+
+/**
+ Clear Sleep Type register.
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval EFI_SUCCESS - Always
+**/
+EFI_STATUS
+ClearSlpTyp (
+ TXT_PEI_LIB_CONTEXT *pctx
+ );
+
+/**
+ Invokes the SCLEAN function from the TXT BIOS ACM.
+ 1. Clearing of sleep type is necessary because SCLEAN destroys memory
+ context, so S3 after it is run and system is reset is impossible. We
+ do it here since there is no any indication that can sustain reset
+ for any other module to do it on our behalf.
+ 2. APs are initialized before calling of SCLEAN
+ 3. SCLEAN function is invoked.
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval EFI_SUCCESS - Always.
+**/
+
+EFI_STATUS
+DoSclean (
+ TXT_PEI_LIB_CONTEXT *pctx
+ );
+
+/**
+ Determines presence of TPM in system
+
+ @param[in] pctx - Point to TXT_PEI_LIB_CONTEXT structure
+
+ @retval EFI_SUCCESS - If the TPM is present.
+ @retval EFI_NOT_FOUND - If the TPM is not present.
+**/
+EFI_STATUS
+IsTpmPresent (
+ TXT_PEI_LIB_CONTEXT *pctx
+ );
+
+/**
+ Searches PEI firemare volume (FV_BB) for file containig BIOS ACM.
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+ @param[in] pBIOSAC_BASE - A pointer to pointer to variable to hold found address
+
+ @retval EFI_SUCCESS - If address has been found
+ @retval EFI_NOT_FOUND - If address has not been found
+**/
+EFI_STATUS
+FindBiosAcmInVolume (
+ TXT_PEI_LIB_CONTEXT *pctx,
+ OUT UINT32 **pBIOSAC_BASE
+ );
+
+/**
+ Searches PEI firmware volume (FV_BB) for file containig AP Startup code
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+ @param[in] pAP_STARTUP - A pointer to pointer to variable to hold address
+ @param[in] address.
+
+ @retval EFI_SUCCESS - If address has been found
+ @retval EFI_NOT_FOUND - If address has not been found
+**/
+EFI_STATUS
+FindApStartupInVolume (
+ TXT_PEI_LIB_CONTEXT *pctx,
+ OUT UINT32 **pAP_STARTUP
+ );
+
+/**
+ Searches PEI firmware volume (FV_BB) for offset of currently loaded MCU patch
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+ @param[in] pMCU - A pointer to pointer to variable to hold found offset
+ @param[in] address.
+
+ @retval EFI_SUCCESS - If address has been found
+ @retval EFI_NOT_FOUND - If address has not been found
+**/
+EFI_STATUS
+FindMcuInVolume (
+ TXT_PEI_LIB_CONTEXT *pctx,
+ OUT UINT32 **pMCU
+ );
+
+/**
+ Searches PEI firmware volume (FV_BB) for the file with specified GUID through pGuid
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+ @param[in] pGuid - A pointer GUID
+ @param[in] pModule - A pointer to pointer to variable to hold address
+
+ @retval EFI_SUCCESS - If address has been found
+ @retval EFI ERROR - If address has not been found
+**/
+EFI_STATUS
+FindModuleInFlash (
+ TXT_PEI_LIB_CONTEXT *pctx,
+ EFI_GUID *pGuid,
+ OUT UINT32 **pModule
+ );
+
+/**
+ Parses Hob list for TXT Info HOB
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval EFI_SUCCESS - If TXT Info Hob is found
+ @retval EFI_NOT_FOUND - If TXT Info Hob is not found
+**/
+EFI_STATUS
+CreateTxtInfoHob (
+ TXT_PEI_LIB_CONTEXT *pctx
+ );
+
+/**
+ Unlock memory when security is set ant TxT is not enabled
+
+ @param[in] pctx - A pointer to an initialized TXT PEI Context data structure
+
+ @retval EFI_SUCCESS - Complete memory unlock
+ @exception EFI_UNSUPPORTED - CPU doesn't support TxT.
+**/
+EFI_STATUS
+UnlockMemory (
+ IN TXT_PEI_LIB_CONTEXT *pctx
+ );
+
+/**
+ Fix up pointers since they are located in real memory now.
+
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] NotifyDescriptor The notification structure this PEIM registered on install.
+ @param[in] Ppi The memory discovered PPI. Not used.
+
+ @retval EFI_SUCCESS The function completed successfully.
+**/
+EFI_STATUS
+DprUpdate (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ );
+
+#endif
diff --git a/ReferenceCode/Haswell/Txt/TxtInit/Pei/Txtpei.cif b/ReferenceCode/Haswell/Txt/TxtInit/Pei/Txtpei.cif
new file mode 100644
index 0000000..7cba3eb
--- /dev/null
+++ b/ReferenceCode/Haswell/Txt/TxtInit/Pei/Txtpei.cif
@@ -0,0 +1,19 @@
+<component>
+ name = "TxtPei"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\Haswell\Txt\TxtInit\Pei\"
+ RefName = "TxtPei"
+[files]
+"TxtPei.sdl"
+"TxtPei.mak"
+"TxtPei.c"
+"TxtPeiLib.c"
+"TxtPeiLib.h"
+"TxtPei.dxs"
+"TxtPei.inf"
+"Ia32\TxtPeiBsp.asm"
+"Ia32\TxtPeiAp.asm16"
+"Ia32\TxtPeiAp.inf"
+"Ia32\TxtPeiApV7.inf"
+"Ia32\makefile.new"
+<endComponent>